s3-libsmb: move protos to libsmb/proto.h
[obnox/samba/samba-obnox.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.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
56 /* macros stolen from s4 spoolss server */
57 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
58         ((info)?ndr_size_##fn(info, level, 0):0)
59
60 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
61         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
62
63 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
64         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
65
66 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
67
68 #undef DBGC_CLASS
69 #define DBGC_CLASS DBGC_RPC_SRV
70
71 #ifndef MAX_OPEN_PRINTER_EXS
72 #define MAX_OPEN_PRINTER_EXS 50
73 #endif
74
75 struct notify_back_channel;
76
77 /* structure to store the printer handles */
78 /* and a reference to what it's pointing to */
79 /* and the notify info asked about */
80 /* that's the central struct */
81 struct printer_handle {
82         struct printer_handle *prev, *next;
83         bool document_started;
84         bool page_started;
85         uint32 jobid; /* jobid in printing backend */
86         int printer_type;
87         const char *servername;
88         fstring sharename;
89         uint32 type;
90         uint32 access_granted;
91         struct {
92                 uint32 flags;
93                 uint32 options;
94                 fstring localmachine;
95                 uint32 printerlocal;
96                 struct spoolss_NotifyOption *option;
97                 struct policy_handle cli_hnd;
98                 struct notify_back_channel *cli_chan;
99                 uint32 change;
100                 /* are we in a FindNextPrinterChangeNotify() call? */
101                 bool fnpcn;
102                 struct messaging_context *msg_ctx;
103         } notify;
104         struct {
105                 fstring machine;
106                 fstring user;
107         } client;
108
109         /* devmode sent in the OpenPrinter() call */
110         struct spoolss_DeviceMode *devmode;
111
112         /* TODO cache the printer info2 structure */
113         struct spoolss_PrinterInfo2 *info2;
114
115 };
116
117 static struct printer_handle *printers_list;
118
119 struct printer_session_counter {
120         struct printer_session_counter *next;
121         struct printer_session_counter *prev;
122
123         int snum;
124         uint32_t counter;
125 };
126
127 static struct printer_session_counter *counter_list;
128
129 struct notify_back_channel {
130         struct notify_back_channel *prev, *next;
131
132         /* associated client */
133         struct sockaddr_storage client_address;
134
135         /* print notify back-channel pipe handle*/
136         struct rpc_pipe_client *cli_pipe;
137         struct dcerpc_binding_handle *binding_handle;
138         uint32_t active_connections;
139 };
140
141 static struct notify_back_channel *back_channels;
142
143 /* Map generic permissions to printer object specific permissions */
144
145 const struct standard_mapping printer_std_mapping = {
146         PRINTER_READ,
147         PRINTER_WRITE,
148         PRINTER_EXECUTE,
149         PRINTER_ALL_ACCESS
150 };
151
152 /* Map generic permissions to print server object specific permissions */
153
154 const struct standard_mapping printserver_std_mapping = {
155         SERVER_READ,
156         SERVER_WRITE,
157         SERVER_EXECUTE,
158         SERVER_ALL_ACCESS
159 };
160
161 /* API table for Xcv Monitor functions */
162
163 struct xcv_api_table {
164         const char *name;
165         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
166 };
167
168 static void prune_printername_cache(void);
169
170 /********************************************************************
171  * Canonicalize servername.
172  ********************************************************************/
173
174 static const char *canon_servername(const char *servername)
175 {
176         const char *pservername = servername;
177         while (*pservername == '\\') {
178                 pservername++;
179         }
180         return pservername;
181 }
182
183 /* translate between internal status numbers and NT status numbers */
184 static int nt_printj_status(int v)
185 {
186         switch (v) {
187         case LPQ_QUEUED:
188                 return 0;
189         case LPQ_PAUSED:
190                 return JOB_STATUS_PAUSED;
191         case LPQ_SPOOLING:
192                 return JOB_STATUS_SPOOLING;
193         case LPQ_PRINTING:
194                 return JOB_STATUS_PRINTING;
195         case LPQ_ERROR:
196                 return JOB_STATUS_ERROR;
197         case LPQ_DELETING:
198                 return JOB_STATUS_DELETING;
199         case LPQ_OFFLINE:
200                 return JOB_STATUS_OFFLINE;
201         case LPQ_PAPEROUT:
202                 return JOB_STATUS_PAPEROUT;
203         case LPQ_PRINTED:
204                 return JOB_STATUS_PRINTED;
205         case LPQ_DELETED:
206                 return JOB_STATUS_DELETED;
207         case LPQ_BLOCKED:
208                 return JOB_STATUS_BLOCKED_DEVQ;
209         case LPQ_USER_INTERVENTION:
210                 return JOB_STATUS_USER_INTERVENTION;
211         }
212         return 0;
213 }
214
215 static int nt_printq_status(int v)
216 {
217         switch (v) {
218         case LPQ_PAUSED:
219                 return PRINTER_STATUS_PAUSED;
220         case LPQ_QUEUED:
221         case LPQ_SPOOLING:
222         case LPQ_PRINTING:
223                 return 0;
224         }
225         return 0;
226 }
227
228 /***************************************************************************
229  Disconnect from the client
230 ****************************************************************************/
231
232 static void srv_spoolss_replycloseprinter(int snum,
233                                           struct printer_handle *prn_hnd)
234 {
235         WERROR result;
236         NTSTATUS status;
237
238         /*
239          * Tell the specific printing tdb we no longer want messages for this printer
240          * by deregistering our PID.
241          */
242
243         if (!print_notify_deregister_pid(snum)) {
244                 DEBUG(0, ("Failed to register our pid for printer %s\n",
245                           lp_const_servicename(snum)));
246         }
247
248         /* weird if the test succeeds !!! */
249         if (prn_hnd->notify.cli_chan == NULL ||
250             prn_hnd->notify.cli_chan->active_connections == 0) {
251                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
252                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
253                 TALLOC_FREE(prn_hnd->notify.cli_chan);
254                 return;
255         }
256
257         status = dcerpc_spoolss_ReplyClosePrinter(
258                                         prn_hnd->notify.cli_chan->binding_handle,
259                                         talloc_tos(),
260                                         &prn_hnd->notify.cli_hnd,
261                                         &result);
262         if (!NT_STATUS_IS_OK(status)) {
263                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
264                           nt_errstr(status)));
265                 result = ntstatus_to_werror(status);
266         } else if (!W_ERROR_IS_OK(result)) {
267                 DEBUG(0, ("reply_close_printer failed [%s].\n",
268                           win_errstr(result)));
269         }
270
271         /* if it's the last connection, deconnect the IPC$ share */
272         if (prn_hnd->notify.cli_chan->active_connections == 1) {
273
274                 prn_hnd->notify.cli_chan->binding_handle = NULL;
275                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
276                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
277                 TALLOC_FREE(prn_hnd->notify.cli_chan);
278
279                 if (prn_hnd->notify.msg_ctx != NULL) {
280                         messaging_deregister(prn_hnd->notify.msg_ctx,
281                                              MSG_PRINTER_NOTIFY2, NULL);
282
283                         /*
284                          * Tell the serverid.tdb we're no longer
285                          * interested in printer notify messages.
286                          */
287
288                         serverid_register_msg_flags(
289                                 messaging_server_id(prn_hnd->notify.msg_ctx),
290                                 false, FLAG_MSG_PRINT_NOTIFY);
291                 }
292         }
293
294         if (prn_hnd->notify.cli_chan) {
295                 prn_hnd->notify.cli_chan->active_connections--;
296         }
297 }
298
299 /****************************************************************************
300  Functions to free a printer entry datastruct.
301 ****************************************************************************/
302
303 static int printer_entry_destructor(struct printer_handle *Printer)
304 {
305         if (Printer->notify.cli_chan != NULL &&
306             Printer->notify.cli_chan->active_connections > 0) {
307                 int snum = -1;
308
309                 switch(Printer->printer_type) {
310                 case SPLHND_SERVER:
311                         srv_spoolss_replycloseprinter(snum, Printer);
312                         break;
313
314                 case SPLHND_PRINTER:
315                         snum = print_queue_snum(Printer->sharename);
316                         if (snum != -1) {
317                                 srv_spoolss_replycloseprinter(snum, Printer);
318                         }
319                         break;
320                 default:
321                         break;
322                 }
323         }
324
325         Printer->notify.flags=0;
326         Printer->notify.options=0;
327         Printer->notify.localmachine[0]='\0';
328         Printer->notify.printerlocal=0;
329         TALLOC_FREE(Printer->notify.option);
330         TALLOC_FREE(Printer->devmode);
331
332         /* Remove from the internal list. */
333         DLIST_REMOVE(printers_list, Printer);
334         return 0;
335 }
336
337 /****************************************************************************
338   find printer index by handle
339 ****************************************************************************/
340
341 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
342                                                         struct policy_handle *hnd)
343 {
344         struct printer_handle *find_printer = NULL;
345
346         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
347                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
348                 return NULL;
349         }
350
351         return find_printer;
352 }
353
354 /****************************************************************************
355  Close printer index by handle.
356 ****************************************************************************/
357
358 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
359 {
360         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
361
362         if (!Printer) {
363                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
364                         OUR_HANDLE(hnd)));
365                 return false;
366         }
367
368         close_policy_hnd(p, hnd);
369
370         return true;
371 }
372
373 /****************************************************************************
374  Delete a printer given a handle.
375 ****************************************************************************/
376
377 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
378                                   const char *sharename,
379                                   struct messaging_context *msg_ctx)
380 {
381         char *cmd = lp_deleteprinter_cmd();
382         char *command = NULL;
383         int ret;
384         bool is_print_op = false;
385
386         /* can't fail if we don't try */
387
388         if ( !*cmd )
389                 return WERR_OK;
390
391         command = talloc_asprintf(ctx,
392                         "%s \"%s\"",
393                         cmd, sharename);
394         if (!command) {
395                 return WERR_NOMEM;
396         }
397         if ( token )
398                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
399
400         DEBUG(10,("Running [%s]\n", command));
401
402         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
403
404         if ( is_print_op )
405                 become_root();
406
407         if ( (ret = smbrun(command, NULL)) == 0 ) {
408                 /* Tell everyone we updated smb.conf. */
409                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
410         }
411
412         if ( is_print_op )
413                 unbecome_root();
414
415         /********** END SePrintOperatorPrivlege BLOCK **********/
416
417         DEBUGADD(10,("returned [%d]\n", ret));
418
419         TALLOC_FREE(command);
420
421         if (ret != 0)
422                 return WERR_BADFID; /* What to return here? */
423
424         /* go ahead and re-read the services immediately */
425         become_root();
426         reload_services(msg_ctx, -1, false);
427         unbecome_root();
428
429         if ( lp_servicenumber( sharename ) >= 0 )
430                 return WERR_ACCESS_DENIED;
431
432         return WERR_OK;
433 }
434
435 /****************************************************************************
436  Delete a printer given a handle.
437 ****************************************************************************/
438
439 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
440 {
441         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
442         WERROR result;
443
444         if (!Printer) {
445                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
446                         OUR_HANDLE(hnd)));
447                 return WERR_BADFID;
448         }
449
450         /*
451          * It turns out that Windows allows delete printer on a handle
452          * opened by an admin user, then used on a pipe handle created
453          * by an anonymous user..... but they're working on security.... riiight !
454          * JRA.
455          */
456
457         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
458                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
459                 return WERR_ACCESS_DENIED;
460         }
461
462         /* this does not need a become root since the access check has been
463            done on the handle already */
464
465         result = winreg_delete_printer_key(p->mem_ctx,
466                                            get_session_info_system(),
467                                            p->msg_ctx,
468                                            Printer->sharename,
469                                            "");
470         if (!W_ERROR_IS_OK(result)) {
471                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
472                 return WERR_BADFID;
473         }
474
475         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
476                                      Printer->sharename, p->msg_ctx);
477         if (!W_ERROR_IS_OK(result)) {
478                 return result;
479         }
480         prune_printername_cache();
481         return WERR_OK;
482 }
483
484 /****************************************************************************
485  Return the snum of a printer corresponding to an handle.
486 ****************************************************************************/
487
488 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
489                              int *number, struct share_params **params)
490 {
491         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
492
493         if (!Printer) {
494                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
495                         OUR_HANDLE(hnd)));
496                 return false;
497         }
498
499         switch (Printer->printer_type) {
500                 case SPLHND_PRINTER:
501                         DEBUG(4,("short name:%s\n", Printer->sharename));
502                         *number = print_queue_snum(Printer->sharename);
503                         return (*number != -1);
504                 case SPLHND_SERVER:
505                         return false;
506                 default:
507                         return false;
508         }
509 }
510
511 /****************************************************************************
512  Set printer handle type.
513  Check if it's \\server or \\server\printer
514 ****************************************************************************/
515
516 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
517 {
518         DEBUG(3,("Setting printer type=%s\n", handlename));
519
520         /* it's a print server */
521         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
522                 DEBUGADD(4,("Printer is a print server\n"));
523                 Printer->printer_type = SPLHND_SERVER;
524         }
525         /* it's a printer (set_printer_hnd_name() will handle port monitors */
526         else {
527                 DEBUGADD(4,("Printer is a printer\n"));
528                 Printer->printer_type = SPLHND_PRINTER;
529         }
530
531         return true;
532 }
533
534 static void prune_printername_cache_fn(const char *key, const char *value,
535                                        time_t timeout, void *private_data)
536 {
537         gencache_del(key);
538 }
539
540 static void prune_printername_cache(void)
541 {
542         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
543 }
544
545 /****************************************************************************
546  Set printer handle name..  Accept names like \\server, \\server\printer,
547  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
548  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
549  XcvDataPort() interface.
550 ****************************************************************************/
551
552 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
553                                    const struct auth_serversupplied_info *session_info,
554                                    struct messaging_context *msg_ctx,
555                                    struct printer_handle *Printer,
556                                    const char *handlename)
557 {
558         int snum;
559         int n_services=lp_numservices();
560         char *aprinter;
561         const char *printername;
562         const char *servername = NULL;
563         fstring sname;
564         bool found = false;
565         struct spoolss_PrinterInfo2 *info2 = NULL;
566         WERROR result;
567         char *p;
568
569         /*
570          * Hopefully nobody names his printers like this. Maybe \ or ,
571          * are illegal in printer names even?
572          */
573         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
574         char *cache_key;
575         char *tmp;
576
577         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
578                 (unsigned long)strlen(handlename)));
579
580         aprinter = discard_const_p(char, handlename);
581         if ( *handlename == '\\' ) {
582                 servername = canon_servername(handlename);
583                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
584                         *aprinter = '\0';
585                         aprinter++;
586                 }
587                 if (!is_myname_or_ipaddr(servername)) {
588                         return WERR_INVALID_PRINTER_NAME;
589                 }
590                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
591                 if (Printer->servername == NULL) {
592                         return WERR_NOMEM;
593                 }
594         }
595
596         if (Printer->printer_type == SPLHND_SERVER) {
597                 return WERR_OK;
598         }
599
600         if (Printer->printer_type != SPLHND_PRINTER) {
601                 return WERR_INVALID_HANDLE;
602         }
603
604         DEBUGADD(5, ("searching for [%s]\n", aprinter));
605
606         p = strchr(aprinter, ',');
607         if (p != NULL) {
608                 char *p2 = p;
609                 p++;
610                 if (*p == ' ') {
611                         p++;
612                 }
613                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
614                         *p2 = '\0';
615                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
616                         *p2 = '\0';
617                 }
618         }
619
620         if (p) {
621                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
622         }
623
624         /* check for the Port Monitor Interface */
625         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
626                 Printer->printer_type = SPLHND_PORTMON_TCP;
627                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
628                 found = true;
629         }
630         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
631                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
632                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
633                 found = true;
634         }
635
636         /*
637          * With hundreds of printers, the "for" loop iterating all
638          * shares can be quite expensive, as it is done on every
639          * OpenPrinter. The loop maps "aprinter" to "sname", the
640          * result of which we cache in gencache.
641          */
642
643         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
644                                     aprinter);
645         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
646
647                 found = (strcmp(tmp, printer_not_found) != 0);
648                 if (!found) {
649                         DEBUG(4, ("Printer %s not found\n", aprinter));
650                         SAFE_FREE(tmp);
651                         return WERR_INVALID_PRINTER_NAME;
652                 }
653                 fstrcpy(sname, tmp);
654                 SAFE_FREE(tmp);
655         }
656
657         /* Search all sharenames first as this is easier than pulling
658            the printer_info_2 off of disk. Don't use find_service() since
659            that calls out to map_username() */
660
661         /* do another loop to look for printernames */
662         for (snum = 0; !found && snum < n_services; snum++) {
663                 const char *printer = lp_const_servicename(snum);
664
665                 /* no point going on if this is not a printer */
666                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
667                         continue;
668                 }
669
670                 /* ignore [printers] share */
671                 if (strequal(printer, "printers")) {
672                         continue;
673                 }
674
675                 fstrcpy(sname, printer);
676                 if (strequal(aprinter, printer)) {
677                         found = true;
678                         break;
679                 }
680
681                 /* no point looking up the printer object if
682                    we aren't allowing printername != sharename */
683                 if (lp_force_printername(snum)) {
684                         continue;
685                 }
686
687                 result = winreg_get_printer(mem_ctx,
688                                             session_info,
689                                             msg_ctx,
690                                             sname,
691                                             &info2);
692                 if ( !W_ERROR_IS_OK(result) ) {
693                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
694                                  sname, win_errstr(result)));
695                         continue;
696                 }
697
698                 printername = strrchr(info2->printername, '\\');
699                 if (printername == NULL) {
700                         printername = info2->printername;
701                 } else {
702                         printername++;
703                 }
704
705                 if (strequal(printername, aprinter)) {
706                         found = true;
707                         break;
708                 }
709
710                 DEBUGADD(10, ("printername: %s\n", printername));
711
712                 TALLOC_FREE(info2);
713         }
714
715         if ( !found ) {
716                 if (cache_key != NULL) {
717                         gencache_set(cache_key, printer_not_found,
718                                      time(NULL)+300);
719                         TALLOC_FREE(cache_key);
720                 }
721                 DEBUGADD(4,("Printer not found\n"));
722                 return WERR_INVALID_PRINTER_NAME;
723         }
724
725         if (cache_key != NULL) {
726                 gencache_set(cache_key, sname, time(NULL)+300);
727                 TALLOC_FREE(cache_key);
728         }
729
730         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
731
732         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
733
734         return WERR_OK;
735 }
736
737 /****************************************************************************
738  Find first available printer slot. creates a printer handle for you.
739  ****************************************************************************/
740
741 static WERROR open_printer_hnd(struct pipes_struct *p,
742                                struct policy_handle *hnd,
743                                const char *name,
744                                uint32_t access_granted)
745 {
746         struct printer_handle *new_printer;
747         WERROR result;
748
749         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
750
751         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
752         if (new_printer == NULL) {
753                 return WERR_NOMEM;
754         }
755         talloc_set_destructor(new_printer, printer_entry_destructor);
756
757         /* This also steals the printer_handle on the policy_handle */
758         if (!create_policy_hnd(p, hnd, new_printer)) {
759                 TALLOC_FREE(new_printer);
760                 return WERR_INVALID_HANDLE;
761         }
762
763         /* Add to the internal list. */
764         DLIST_ADD(printers_list, new_printer);
765
766         new_printer->notify.option=NULL;
767
768         if (!set_printer_hnd_printertype(new_printer, name)) {
769                 close_printer_handle(p, hnd);
770                 return WERR_INVALID_HANDLE;
771         }
772
773         result = set_printer_hnd_name(p->mem_ctx,
774                                       get_session_info_system(),
775                                       p->msg_ctx,
776                                       new_printer, name);
777         if (!W_ERROR_IS_OK(result)) {
778                 close_printer_handle(p, hnd);
779                 return result;
780         }
781
782         new_printer->access_granted = access_granted;
783
784         DEBUG(5, ("%d printer handles active\n",
785                   (int)num_pipe_handles(p)));
786
787         return WERR_OK;
788 }
789
790 /***************************************************************************
791  check to see if the client motify handle is monitoring the notification
792  given by (notify_type, notify_field).
793  **************************************************************************/
794
795 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
796                                       uint16_t notify_field)
797 {
798         return true;
799 }
800
801 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
802                                 uint16_t notify_field)
803 {
804         struct spoolss_NotifyOption *option = p->notify.option;
805         uint32_t i, j;
806
807         /*
808          * Flags should always be zero when the change notify
809          * is registered by the client's spooler.  A user Win32 app
810          * might use the flags though instead of the NOTIFY_OPTION_INFO
811          * --jerry
812          */
813
814         if (!option) {
815                 return false;
816         }
817
818         if (p->notify.flags)
819                 return is_monitoring_event_flags(
820                         p->notify.flags, notify_type, notify_field);
821
822         for (i = 0; i < option->count; i++) {
823
824                 /* Check match for notify_type */
825
826                 if (option->types[i].type != notify_type)
827                         continue;
828
829                 /* Check match for field */
830
831                 for (j = 0; j < option->types[i].count; j++) {
832                         if (option->types[i].fields[j].field == notify_field) {
833                                 return true;
834                         }
835                 }
836         }
837
838         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
839                    p->servername, p->sharename, notify_type, notify_field));
840
841         return false;
842 }
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
845         _data->data.integer[0] = _integer; \
846         _data->data.integer[1] = 0;
847
848
849 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
850         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
851         if (!_data->data.string.string) {\
852                 _data->data.string.size = 0; \
853         } \
854         _data->data.string.size = strlen_m_term(_p) * 2;
855
856 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
857         _data->data.devmode.devmode = _devmode;
858
859 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
860         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
861         if (!_data->data.sd.sd) { \
862                 _data->data.sd.sd_size = 0; \
863         } \
864         _data->data.sd.sd_size = \
865                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
866
867 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
868                                    struct tm *t,
869                                    const char **pp,
870                                    uint32_t *plen)
871 {
872         struct spoolss_Time st;
873         uint32_t len = 16;
874         char *p;
875
876         if (!init_systemtime(&st, t)) {
877                 return;
878         }
879
880         p = talloc_array(mem_ctx, char, len);
881         if (!p) {
882                 return;
883         }
884
885         /*
886          * Systemtime must be linearized as a set of UINT16's.
887          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
888          */
889
890         SSVAL(p, 0, st.year);
891         SSVAL(p, 2, st.month);
892         SSVAL(p, 4, st.day_of_week);
893         SSVAL(p, 6, st.day);
894         SSVAL(p, 8, st.hour);
895         SSVAL(p, 10, st.minute);
896         SSVAL(p, 12, st.second);
897         SSVAL(p, 14, st.millisecond);
898
899         *pp = p;
900         *plen = len;
901 }
902
903 /* Convert a notification message to a struct spoolss_Notify */
904
905 static void notify_one_value(struct spoolss_notify_msg *msg,
906                              struct spoolss_Notify *data,
907                              TALLOC_CTX *mem_ctx)
908 {
909         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
910 }
911
912 static void notify_string(struct spoolss_notify_msg *msg,
913                           struct spoolss_Notify *data,
914                           TALLOC_CTX *mem_ctx)
915 {
916         /* The length of the message includes the trailing \0 */
917
918         data->data.string.size = msg->len * 2;
919         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
920         if (!data->data.string.string) {
921                 data->data.string.size = 0;
922                 return;
923         }
924 }
925
926 static void notify_system_time(struct spoolss_notify_msg *msg,
927                                struct spoolss_Notify *data,
928                                TALLOC_CTX *mem_ctx)
929 {
930         data->data.string.string = NULL;
931         data->data.string.size = 0;
932
933         if (msg->len != sizeof(time_t)) {
934                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
935                           msg->len));
936                 return;
937         }
938
939         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
940                                &data->data.string.string,
941                                &data->data.string.size);
942 }
943
944 struct notify2_message_table {
945         const char *name;
946         void (*fn)(struct spoolss_notify_msg *msg,
947                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
948 };
949
950 static struct notify2_message_table printer_notify_table[] = {
951         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
952         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
953         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
954         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
955         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
956         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
957         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
958         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
959         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
960         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
961         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
962         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
963         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
964         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
965         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
966         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
967         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
968         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
969         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
970 };
971
972 static struct notify2_message_table job_notify_table[] = {
973         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
974         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
975         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
976         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
977         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
978         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
979         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
980         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
981         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
982         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
983         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
984         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
985         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
986         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
987         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
988         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
989         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
990         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
991         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
992         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
993         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
994         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
995         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
996         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
997 };
998
999
1000 /***********************************************************************
1001  Allocate talloc context for container object
1002  **********************************************************************/
1003
1004 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1005 {
1006         if ( !ctr )
1007                 return;
1008
1009         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1010
1011         return;
1012 }
1013
1014 /***********************************************************************
1015  release all allocated memory and zero out structure
1016  **********************************************************************/
1017
1018 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1019 {
1020         if ( !ctr )
1021                 return;
1022
1023         if ( ctr->ctx )
1024                 talloc_destroy(ctr->ctx);
1025
1026         ZERO_STRUCTP(ctr);
1027
1028         return;
1029 }
1030
1031 /***********************************************************************
1032  **********************************************************************/
1033
1034 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1035 {
1036         if ( !ctr )
1037                 return NULL;
1038
1039         return ctr->ctx;
1040 }
1041
1042 /***********************************************************************
1043  **********************************************************************/
1044
1045 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1046 {
1047         if ( !ctr || !ctr->msg_groups )
1048                 return NULL;
1049
1050         if ( idx >= ctr->num_groups )
1051                 return NULL;
1052
1053         return &ctr->msg_groups[idx];
1054
1055 }
1056
1057 /***********************************************************************
1058  How many groups of change messages do we have ?
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1062 {
1063         if ( !ctr )
1064                 return 0;
1065
1066         return ctr->num_groups;
1067 }
1068
1069 /***********************************************************************
1070  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1071  **********************************************************************/
1072
1073 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1074 {
1075         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1076         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1077         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1078         int                             i, new_slot;
1079
1080         if ( !ctr || !msg )
1081                 return 0;
1082
1083         /* loop over all groups looking for a matching printer name */
1084
1085         for ( i=0; i<ctr->num_groups; i++ ) {
1086                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1087                         break;
1088         }
1089
1090         /* add a new group? */
1091
1092         if ( i == ctr->num_groups ) {
1093                 ctr->num_groups++;
1094
1095                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1096                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1097                         return 0;
1098                 }
1099                 ctr->msg_groups = groups;
1100
1101                 /* clear the new entry and set the printer name */
1102
1103                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1104                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1105         }
1106
1107         /* add the change messages; 'i' is the correct index now regardless */
1108
1109         msg_grp = &ctr->msg_groups[i];
1110
1111         msg_grp->num_msgs++;
1112
1113         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1114                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1115                 return 0;
1116         }
1117         msg_grp->msgs = msg_list;
1118
1119         new_slot = msg_grp->num_msgs-1;
1120         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1121
1122         /* need to allocate own copy of data */
1123
1124         if ( msg->len != 0 )
1125                 msg_grp->msgs[new_slot].notify.data = (char *)
1126                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1127
1128         return ctr->num_groups;
1129 }
1130
1131 static void construct_info_data(struct spoolss_Notify *info_data,
1132                                 enum spoolss_NotifyType type,
1133                                 uint16_t field, int id);
1134
1135 /***********************************************************************
1136  Send a change notication message on all handles which have a call
1137  back registered
1138  **********************************************************************/
1139
1140 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1141                                   struct printer_handle *prn_hnd,
1142                                   SPOOLSS_NOTIFY_MSG *messages,
1143                                   uint32_t num_msgs,
1144                                   struct spoolss_Notify **_notifies,
1145                                   int *_count)
1146 {
1147         struct spoolss_Notify *notifies;
1148         SPOOLSS_NOTIFY_MSG *msg;
1149         int count = 0;
1150         uint32_t id;
1151         int i;
1152
1153         notifies = talloc_zero_array(mem_ctx,
1154                                      struct spoolss_Notify, num_msgs);
1155         if (!notifies) {
1156                 return ENOMEM;
1157         }
1158
1159         for (i = 0; i < num_msgs; i++) {
1160
1161                 msg = &messages[i];
1162
1163                 /* Are we monitoring this event? */
1164
1165                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1166                         continue;
1167                 }
1168
1169                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1170                            "for printer [%s]\n",
1171                            msg->type, msg->field, prn_hnd->sharename));
1172
1173                 /*
1174                  * if the is a printer notification handle and not a job
1175                  * notification type, then set the id to 0.
1176                  * Otherwise just use what was specified in the message.
1177                  *
1178                  * When registering change notification on a print server
1179                  * handle we always need to send back the id (snum) matching
1180                  * the printer for which the change took place.
1181                  * For change notify registered on a printer handle,
1182                  * this does not matter and the id should be 0.
1183                  *
1184                  * --jerry
1185                  */
1186
1187                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1188                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1189                         id = 0;
1190                 } else {
1191                         id = msg->id;
1192                 }
1193
1194                 /* Convert unix jobid to smb jobid */
1195
1196                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1197                         id = sysjob_to_jobid(msg->id);
1198
1199                         if (id == -1) {
1200                                 DEBUG(3, ("no such unix jobid %d\n",
1201                                           msg->id));
1202                                 continue;
1203                         }
1204                 }
1205
1206                 construct_info_data(&notifies[count],
1207                                     msg->type, msg->field, id);
1208
1209                 switch(msg->type) {
1210                 case PRINTER_NOTIFY_TYPE:
1211                         if (printer_notify_table[msg->field].fn) {
1212                                 printer_notify_table[msg->field].fn(msg,
1213                                                 &notifies[count], mem_ctx);
1214                         }
1215                         break;
1216
1217                 case JOB_NOTIFY_TYPE:
1218                         if (job_notify_table[msg->field].fn) {
1219                                 job_notify_table[msg->field].fn(msg,
1220                                                 &notifies[count], mem_ctx);
1221                         }
1222                         break;
1223
1224                 default:
1225                         DEBUG(5, ("Unknown notification type %d\n",
1226                                   msg->type));
1227                         continue;
1228                 }
1229
1230                 count++;
1231         }
1232
1233         *_notifies = notifies;
1234         *_count = count;
1235
1236         return 0;
1237 }
1238
1239 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1240                                 struct printer_handle *prn_hnd,
1241                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1242 {
1243         struct spoolss_Notify *notifies;
1244         int count = 0;
1245         union spoolss_ReplyPrinterInfo info;
1246         struct spoolss_NotifyInfo info0;
1247         uint32_t reply_result;
1248         NTSTATUS status;
1249         WERROR werr;
1250         int ret;
1251
1252         /* Is there notification on this handle? */
1253         if (prn_hnd->notify.cli_chan == NULL ||
1254             prn_hnd->notify.cli_chan->active_connections == 0) {
1255                 return 0;
1256         }
1257
1258         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1259                    prn_hnd->servername, prn_hnd->sharename));
1260
1261         /* For this printer? Print servers always receive notifications. */
1262         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1263             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1264                 return 0;
1265         }
1266
1267         DEBUG(10,("Our printer\n"));
1268
1269         /* build the array of change notifications */
1270         ret = build_notify2_messages(mem_ctx, prn_hnd,
1271                                      msg_group->msgs,
1272                                      msg_group->num_msgs,
1273                                      &notifies, &count);
1274         if (ret) {
1275                 return ret;
1276         }
1277
1278         info0.version   = 0x2;
1279         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1280         info0.count     = count;
1281         info0.notifies  = notifies;
1282
1283         info.info0 = &info0;
1284
1285         status = dcerpc_spoolss_RouterReplyPrinterEx(
1286                                 prn_hnd->notify.cli_chan->binding_handle,
1287                                 mem_ctx,
1288                                 &prn_hnd->notify.cli_hnd,
1289                                 prn_hnd->notify.change, /* color */
1290                                 prn_hnd->notify.flags,
1291                                 &reply_result,
1292                                 0, /* reply_type, must be 0 */
1293                                 info, &werr);
1294         if (!NT_STATUS_IS_OK(status)) {
1295                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1296                           "failed: %s\n",
1297                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1298                           nt_errstr(status)));
1299                 werr = ntstatus_to_werror(status);
1300         } else if (!W_ERROR_IS_OK(werr)) {
1301                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1302                           "failed: %s\n",
1303                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1304                           win_errstr(werr)));
1305         }
1306         switch (reply_result) {
1307         case 0:
1308                 break;
1309         case PRINTER_NOTIFY_INFO_DISCARDED:
1310         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1311         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1312                 break;
1313         default:
1314                 break;
1315         }
1316
1317         return 0;
1318 }
1319
1320 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1321 {
1322         struct printer_handle    *p;
1323         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1324         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1325         int ret;
1326
1327         if ( !msg_group ) {
1328                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1329                 return;
1330         }
1331
1332         if (!msg_group->msgs) {
1333                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1334                 return;
1335         }
1336
1337         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1338
1339         /* loop over all printers */
1340
1341         for (p = printers_list; p; p = p->next) {
1342                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1343                 if (ret) {
1344                         goto done;
1345                 }
1346         }
1347
1348 done:
1349         DEBUG(8,("send_notify2_changes: Exit...\n"));
1350         return;
1351 }
1352
1353 /***********************************************************************
1354  **********************************************************************/
1355
1356 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1357 {
1358
1359         uint32_t tv_sec, tv_usec;
1360         size_t offset = 0;
1361
1362         /* Unpack message */
1363
1364         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1365                              msg->printer);
1366
1367         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1368                                 &tv_sec, &tv_usec,
1369                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1370
1371         if (msg->len == 0)
1372                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1373                            &msg->notify.value[0], &msg->notify.value[1]);
1374         else
1375                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1376                            &msg->len, &msg->notify.data);
1377
1378         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1379                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1380
1381         tv->tv_sec = tv_sec;
1382         tv->tv_usec = tv_usec;
1383
1384         if (msg->len == 0)
1385                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1386                           msg->notify.value[1]));
1387         else
1388                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1389
1390         return true;
1391 }
1392
1393 /********************************************************************
1394  Receive a notify2 message list
1395  ********************************************************************/
1396
1397 static void receive_notify2_message_list(struct messaging_context *msg,
1398                                          void *private_data,
1399                                          uint32_t msg_type,
1400                                          struct server_id server_id,
1401                                          DATA_BLOB *data)
1402 {
1403         size_t                  msg_count, i;
1404         char                    *buf = (char *)data->data;
1405         char                    *msg_ptr;
1406         size_t                  msg_len;
1407         SPOOLSS_NOTIFY_MSG      notify;
1408         SPOOLSS_NOTIFY_MSG_CTR  messages;
1409         int                     num_groups;
1410
1411         if (data->length < 4) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1413                 return;
1414         }
1415
1416         msg_count = IVAL(buf, 0);
1417         msg_ptr = buf + 4;
1418
1419         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1420
1421         if (msg_count == 0) {
1422                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1423                 return;
1424         }
1425
1426         /* initialize the container */
1427
1428         ZERO_STRUCT( messages );
1429         notify_msg_ctr_init( &messages );
1430
1431         /*
1432          * build message groups for each printer identified
1433          * in a change_notify msg.  Remember that a PCN message
1434          * includes the handle returned for the srv_spoolss_replyopenprinter()
1435          * call.  Therefore messages are grouped according to printer handle.
1436          */
1437
1438         for ( i=0; i<msg_count; i++ ) {
1439                 struct timeval msg_tv;
1440
1441                 if (msg_ptr + 4 - buf > data->length) {
1442                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1443                         return;
1444                 }
1445
1446                 msg_len = IVAL(msg_ptr,0);
1447                 msg_ptr += 4;
1448
1449                 if (msg_ptr + msg_len - buf > data->length) {
1450                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1451                         return;
1452                 }
1453
1454                 /* unpack messages */
1455
1456                 ZERO_STRUCT( notify );
1457                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1458                 msg_ptr += msg_len;
1459
1460                 /* add to correct list in container */
1461
1462                 notify_msg_ctr_addmsg( &messages, &notify );
1463
1464                 /* free memory that might have been allocated by notify2_unpack_msg() */
1465
1466                 if ( notify.len != 0 )
1467                         SAFE_FREE( notify.notify.data );
1468         }
1469
1470         /* process each group of messages */
1471
1472         num_groups = notify_msg_ctr_numgroups( &messages );
1473         for ( i=0; i<num_groups; i++ )
1474                 send_notify2_changes( &messages, i );
1475
1476
1477         /* cleanup */
1478
1479         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1480                 (uint32_t)msg_count ));
1481
1482         notify_msg_ctr_destroy( &messages );
1483
1484         return;
1485 }
1486
1487 /********************************************************************
1488  Send a message to ourself about new driver being installed
1489  so we can upgrade the information for each printer bound to this
1490  driver
1491  ********************************************************************/
1492
1493 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1494                                             struct messaging_context *msg_ctx)
1495 {
1496         int len = strlen(drivername);
1497
1498         if (!len)
1499                 return false;
1500
1501         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1502                 drivername));
1503
1504         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1505                            MSG_PRINTER_DRVUPGRADE,
1506                            (const uint8_t *)drivername, len+1);
1507
1508         return true;
1509 }
1510
1511 void srv_spoolss_cleanup(void)
1512 {
1513         struct printer_session_counter *session_counter;
1514
1515         for (session_counter = counter_list;
1516              session_counter != NULL;
1517              session_counter = counter_list) {
1518                 DLIST_REMOVE(counter_list, session_counter);
1519                 TALLOC_FREE(session_counter);
1520         }
1521 }
1522
1523 /**********************************************************************
1524  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1525  over all printers, upgrading ones as necessary
1526  **********************************************************************/
1527
1528 void do_drv_upgrade_printer(struct messaging_context *msg,
1529                             void *private_data,
1530                             uint32_t msg_type,
1531                             struct server_id server_id,
1532                             DATA_BLOB *data)
1533 {
1534         TALLOC_CTX *tmp_ctx;
1535         struct auth_serversupplied_info *session_info = NULL;
1536         struct spoolss_PrinterInfo2 *pinfo2;
1537         NTSTATUS status;
1538         WERROR result;
1539         const char *drivername;
1540         int snum;
1541         int n_services = lp_numservices();
1542
1543         tmp_ctx = talloc_new(NULL);
1544         if (!tmp_ctx) return;
1545
1546         status = make_session_info_system(tmp_ctx, &session_info);
1547         if (!NT_STATUS_IS_OK(status)) {
1548                 DEBUG(0, ("do_drv_upgrade_printer: "
1549                           "Could not create system session_info\n"));
1550                 goto done;
1551         }
1552
1553         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1554         if (!drivername) {
1555                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1556                 goto done;
1557         }
1558
1559         DEBUG(10, ("do_drv_upgrade_printer: "
1560                    "Got message for new driver [%s]\n", drivername));
1561
1562         /* Iterate the printer list */
1563
1564         for (snum = 0; snum < n_services; snum++) {
1565                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1566                         continue;
1567                 }
1568
1569                 /* ignore [printers] share */
1570                 if (strequal(lp_const_servicename(snum), "printers")) {
1571                         continue;
1572                 }
1573
1574                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1575                                             lp_const_servicename(snum),
1576                                             &pinfo2);
1577
1578                 if (!W_ERROR_IS_OK(result)) {
1579                         continue;
1580                 }
1581
1582                 if (!pinfo2->drivername) {
1583                         continue;
1584                 }
1585
1586                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1587                         continue;
1588                 }
1589
1590                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1591
1592                 /* all we care about currently is the change_id */
1593                 result = winreg_printer_update_changeid(tmp_ctx,
1594                                                         session_info,
1595                                                         msg,
1596                                                         pinfo2->printername);
1597
1598                 if (!W_ERROR_IS_OK(result)) {
1599                         DEBUG(3, ("do_drv_upgrade_printer: "
1600                                   "Failed to update changeid [%s]\n",
1601                                   win_errstr(result)));
1602                 }
1603         }
1604
1605         /* all done */
1606 done:
1607         talloc_free(tmp_ctx);
1608 }
1609
1610 /********************************************************************
1611  Update the cache for all printq's with a registered client
1612  connection
1613  ********************************************************************/
1614
1615 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1616 {
1617         struct printer_handle *printer = printers_list;
1618         int snum;
1619
1620         /* loop through all printers and update the cache where
1621            a client is connected */
1622         while (printer) {
1623                 if ((printer->printer_type == SPLHND_PRINTER) &&
1624                     ((printer->notify.cli_chan != NULL) &&
1625                      (printer->notify.cli_chan->active_connections > 0))) {
1626                         snum = print_queue_snum(printer->sharename);
1627                         print_queue_status(msg_ctx, snum, NULL, NULL);
1628                 }
1629
1630                 printer = printer->next;
1631         }
1632
1633         return;
1634 }
1635
1636 /****************************************************************
1637  _spoolss_OpenPrinter
1638 ****************************************************************/
1639
1640 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1641                             struct spoolss_OpenPrinter *r)
1642 {
1643         struct spoolss_OpenPrinterEx e;
1644         WERROR werr;
1645
1646         ZERO_STRUCT(e.in.userlevel);
1647
1648         e.in.printername        = r->in.printername;
1649         e.in.datatype           = r->in.datatype;
1650         e.in.devmode_ctr        = r->in.devmode_ctr;
1651         e.in.access_mask        = r->in.access_mask;
1652         e.in.level              = 0;
1653
1654         e.out.handle            = r->out.handle;
1655
1656         werr = _spoolss_OpenPrinterEx(p, &e);
1657
1658         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1659                 /* OpenPrinterEx returns this for a bad
1660                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1661                  * instead.
1662                  */
1663                 werr = WERR_INVALID_PRINTER_NAME;
1664         }
1665
1666         return werr;
1667 }
1668
1669 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1670                               struct spoolss_DeviceMode *orig,
1671                               struct spoolss_DeviceMode **dest)
1672 {
1673         struct spoolss_DeviceMode *dm;
1674
1675         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1676         if (!dm) {
1677                 return WERR_NOMEM;
1678         }
1679
1680         /* copy all values, then duplicate strings and structs */
1681         *dm = *orig;
1682
1683         dm->devicename = talloc_strdup(dm, orig->devicename);
1684         if (!dm->devicename) {
1685                 return WERR_NOMEM;
1686         }
1687         dm->formname = talloc_strdup(dm, orig->formname);
1688         if (!dm->formname) {
1689                 return WERR_NOMEM;
1690         }
1691         if (orig->driverextra_data.data) {
1692                 dm->driverextra_data.data =
1693                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1694                                         orig->driverextra_data.length);
1695                 if (!dm->driverextra_data.data) {
1696                         return WERR_NOMEM;
1697                 }
1698         }
1699
1700         *dest = dm;
1701         return WERR_OK;
1702 }
1703
1704 /****************************************************************
1705  _spoolss_OpenPrinterEx
1706 ****************************************************************/
1707
1708 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1709                               struct spoolss_OpenPrinterEx *r)
1710 {
1711         int snum;
1712         struct printer_handle *Printer=NULL;
1713         WERROR result;
1714
1715         if (!r->in.printername) {
1716                 return WERR_INVALID_PARAM;
1717         }
1718
1719         if (r->in.level > 3) {
1720                 return WERR_INVALID_PARAM;
1721         }
1722         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1723             (r->in.level == 2 && !r->in.userlevel.level2) ||
1724             (r->in.level == 3 && !r->in.userlevel.level3)) {
1725                 return WERR_INVALID_PARAM;
1726         }
1727
1728         /* some sanity check because you can open a printer or a print server */
1729         /* aka: \\server\printer or \\server */
1730
1731         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1732
1733         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1734         if (!W_ERROR_IS_OK(result)) {
1735                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1736                         "for printer %s\n", r->in.printername));
1737                 ZERO_STRUCTP(r->out.handle);
1738                 return result;
1739         }
1740
1741         Printer = find_printer_index_by_hnd(p, r->out.handle);
1742         if ( !Printer ) {
1743                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1744                         "handle we created for printer %s\n", r->in.printername));
1745                 close_printer_handle(p, r->out.handle);
1746                 ZERO_STRUCTP(r->out.handle);
1747                 return WERR_INVALID_PARAM;
1748         }
1749
1750         /*
1751          * First case: the user is opening the print server:
1752          *
1753          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1754          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1755          *
1756          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1757          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1758          * or if the user is listed in the smb.conf printer admin parameter.
1759          *
1760          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1761          * client view printer folder, but does not show the MSAPW.
1762          *
1763          * Note: this test needs code to check access rights here too. Jeremy
1764          * could you look at this?
1765          *
1766          * Second case: the user is opening a printer:
1767          * NT doesn't let us connect to a printer if the connecting user
1768          * doesn't have print permission.
1769          *
1770          * Third case: user is opening a Port Monitor
1771          * access checks same as opening a handle to the print server.
1772          */
1773
1774         switch (Printer->printer_type )
1775         {
1776         case SPLHND_SERVER:
1777         case SPLHND_PORTMON_TCP:
1778         case SPLHND_PORTMON_LOCAL:
1779                 /* Printserver handles use global struct... */
1780
1781                 snum = -1;
1782
1783                 /* Map standard access rights to object specific access rights */
1784
1785                 se_map_standard(&r->in.access_mask,
1786                                 &printserver_std_mapping);
1787
1788                 /* Deny any object specific bits that don't apply to print
1789                    servers (i.e printer and job specific bits) */
1790
1791                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1792
1793                 if (r->in.access_mask &
1794                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796                         close_printer_handle(p, r->out.handle);
1797                         ZERO_STRUCTP(r->out.handle);
1798                         return WERR_ACCESS_DENIED;
1799                 }
1800
1801                 /* Allow admin access */
1802
1803                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1804                 {
1805                         if (!lp_ms_add_printer_wizard()) {
1806                                 close_printer_handle(p, r->out.handle);
1807                                 ZERO_STRUCTP(r->out.handle);
1808                                 return WERR_ACCESS_DENIED;
1809                         }
1810
1811                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812                            and not a printer admin, then fail */
1813
1814                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1815                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1816                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1817                             !token_contains_name_in_list(
1818                                     uidtoname(p->session_info->utok.uid),
1819                                     p->session_info->info3->base.domain.string,
1820                                     NULL,
1821                                     p->session_info->security_token,
1822                                     lp_printer_admin(snum))) {
1823                                 close_printer_handle(p, r->out.handle);
1824                                 ZERO_STRUCTP(r->out.handle);
1825                                 DEBUG(3,("access DENIED as user is not root, "
1826                                         "has no printoperator privilege, "
1827                                         "not a member of the printoperator builtin group and "
1828                                         "is not in printer admin list"));
1829                                 return WERR_ACCESS_DENIED;
1830                         }
1831
1832                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833                 }
1834                 else
1835                 {
1836                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1837                 }
1838
1839                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1840                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1841
1842                 /* We fall through to return WERR_OK */
1843                 break;
1844
1845         case SPLHND_PRINTER:
1846                 /* NT doesn't let us connect to a printer if the connecting user
1847                    doesn't have print permission.  */
1848
1849                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1850                         close_printer_handle(p, r->out.handle);
1851                         ZERO_STRUCTP(r->out.handle);
1852                         return WERR_BADFID;
1853                 }
1854
1855                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1856                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1857                 }
1858
1859                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1860
1861                 /* map an empty access mask to the minimum access mask */
1862                 if (r->in.access_mask == 0x0)
1863                         r->in.access_mask = PRINTER_ACCESS_USE;
1864
1865                 /*
1866                  * If we are not serving the printer driver for this printer,
1867                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1868                  * will keep NT clients happy  --jerry
1869                  */
1870
1871                 if (lp_use_client_driver(snum)
1872                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1873                 {
1874                         r->in.access_mask = PRINTER_ACCESS_USE;
1875                 }
1876
1877                 /* check smb.conf parameters and the the sec_desc */
1878
1879                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1880                                   p->client_id->name, p->client_id->addr)) {
1881                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1882                         ZERO_STRUCTP(r->out.handle);
1883                         return WERR_ACCESS_DENIED;
1884                 }
1885
1886                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1887                                    p->session_info->security_token, snum) ||
1888                     !print_access_check(p->session_info,
1889                                         p->msg_ctx,
1890                                         snum,
1891                                         r->in.access_mask)) {
1892                         DEBUG(3, ("access DENIED for printer open\n"));
1893                         close_printer_handle(p, r->out.handle);
1894                         ZERO_STRUCTP(r->out.handle);
1895                         return WERR_ACCESS_DENIED;
1896                 }
1897
1898                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1899                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1900                         close_printer_handle(p, r->out.handle);
1901                         ZERO_STRUCTP(r->out.handle);
1902                         return WERR_ACCESS_DENIED;
1903                 }
1904
1905                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1906                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1907                 else
1908                         r->in.access_mask = PRINTER_ACCESS_USE;
1909
1910                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1911                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1912
1913                 winreg_create_printer(p->mem_ctx,
1914                                       get_session_info_system(),
1915                                       p->msg_ctx,
1916                                       lp_const_servicename(snum));
1917
1918                 break;
1919
1920         default:
1921                 /* sanity check to prevent programmer error */
1922                 ZERO_STRUCTP(r->out.handle);
1923                 return WERR_BADFID;
1924         }
1925
1926         Printer->access_granted = r->in.access_mask;
1927
1928         /*
1929          * If the client sent a devmode in the OpenPrinter() call, then
1930          * save it here in case we get a job submission on this handle
1931          */
1932
1933          if ((Printer->printer_type != SPLHND_SERVER) &&
1934              r->in.devmode_ctr.devmode) {
1935                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1936                                 &Printer->devmode);
1937          }
1938
1939 #if 0   /* JERRY -- I'm doubtful this is really effective */
1940         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1941            optimization in Windows 2000 clients  --jerry */
1942
1943         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1944                 && (RA_WIN2K == get_remote_arch()) )
1945         {
1946                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1947                 sys_usleep( 500000 );
1948         }
1949 #endif
1950
1951         return WERR_OK;
1952 }
1953
1954 /****************************************************************
1955  _spoolss_ClosePrinter
1956 ****************************************************************/
1957
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959                              struct spoolss_ClosePrinter *r)
1960 {
1961         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962
1963         if (Printer && Printer->document_started) {
1964                 struct spoolss_EndDocPrinter e;
1965
1966                 e.in.handle = r->in.handle;
1967
1968                 _spoolss_EndDocPrinter(p, &e);
1969         }
1970
1971         if (!close_printer_handle(p, r->in.handle))
1972                 return WERR_BADFID;
1973
1974         /* clear the returned printer handle.  Observed behavior
1975            from Win2k server.  Don't think this really matters.
1976            Previous code just copied the value of the closed
1977            handle.    --jerry */
1978
1979         ZERO_STRUCTP(r->out.handle);
1980
1981         return WERR_OK;
1982 }
1983
1984 /****************************************************************
1985  _spoolss_DeletePrinter
1986 ****************************************************************/
1987
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989                               struct spoolss_DeletePrinter *r)
1990 {
1991         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992         WERROR result;
1993         int snum;
1994
1995         if (Printer && Printer->document_started) {
1996                 struct spoolss_EndDocPrinter e;
1997
1998                 e.in.handle = r->in.handle;
1999
2000                 _spoolss_EndDocPrinter(p, &e);
2001         }
2002
2003         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004                 winreg_delete_printer_key(p->mem_ctx,
2005                                           get_session_info_system(),
2006                                           p->msg_ctx,
2007                                           lp_const_servicename(snum),
2008                                           "");
2009         }
2010
2011         result = delete_printer_handle(p, r->in.handle);
2012
2013         return result;
2014 }
2015
2016 /*******************************************************************
2017  * static function to lookup the version id corresponding to an
2018  * long architecture string
2019  ******************************************************************/
2020
2021 static const struct print_architecture_table_node archi_table[]= {
2022
2023         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2024         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2025         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2026         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2027         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2028         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2029         {"Windows x64",          SPL_ARCH_X64,          3 },
2030         {NULL,                   "",            -1 }
2031 };
2032
2033 static int get_version_id(const char *arch)
2034 {
2035         int i;
2036
2037         for (i=0; archi_table[i].long_archi != NULL; i++)
2038         {
2039                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2040                         return (archi_table[i].version);
2041         }
2042
2043         return -1;
2044 }
2045
2046 /****************************************************************
2047  _spoolss_DeletePrinterDriver
2048 ****************************************************************/
2049
2050 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2051                                     struct spoolss_DeletePrinterDriver *r)
2052 {
2053
2054         struct spoolss_DriverInfo8 *info = NULL;
2055         struct spoolss_DriverInfo8 *info_win2k = NULL;
2056         int                             version;
2057         WERROR                          status;
2058
2059         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060            and not a printer admin, then fail */
2061
2062         if ( (p->session_info->utok.uid != sec_initial_uid())
2063              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2064                 && !token_contains_name_in_list(
2065                         uidtoname(p->session_info->utok.uid),
2066                         p->session_info->info3->base.domain.string,
2067                         NULL,
2068                         p->session_info->security_token,
2069                         lp_printer_admin(-1)) )
2070         {
2071                 return WERR_ACCESS_DENIED;
2072         }
2073
2074         /* check that we have a valid driver name first */
2075
2076         if ((version = get_version_id(r->in.architecture)) == -1)
2077                 return WERR_INVALID_ENVIRONMENT;
2078
2079         status = winreg_get_driver(p->mem_ctx,
2080                                    get_session_info_system(),
2081                                    p->msg_ctx,
2082                                    r->in.architecture, r->in.driver,
2083                                    version, &info);
2084         if (!W_ERROR_IS_OK(status)) {
2085                 /* try for Win2k driver if "Windows NT x86" */
2086
2087                 if ( version == 2 ) {
2088                         version = 3;
2089
2090                         status = winreg_get_driver(p->mem_ctx,
2091                                                    get_session_info_system(),
2092                                                    p->msg_ctx,
2093                                                    r->in.architecture,
2094                                                    r->in.driver,
2095                                                    version, &info);
2096                         if (!W_ERROR_IS_OK(status)) {
2097                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2098                                 goto done;
2099                         }
2100                 }
2101                 /* otherwise it was a failure */
2102                 else {
2103                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2104                         goto done;
2105                 }
2106
2107         }
2108
2109         if (printer_driver_in_use(p->mem_ctx,
2110                                   get_session_info_system(),
2111                                   p->msg_ctx,
2112                                   info)) {
2113                 status = WERR_PRINTER_DRIVER_IN_USE;
2114                 goto done;
2115         }
2116
2117         if (version == 2) {
2118                 status = winreg_get_driver(p->mem_ctx,
2119                                            get_session_info_system(),
2120                                            p->msg_ctx,
2121                                            r->in.architecture,
2122                                            r->in.driver, 3, &info_win2k);
2123                 if (W_ERROR_IS_OK(status)) {
2124                         /* if we get to here, we now have 2 driver info structures to remove */
2125                         /* remove the Win2k driver first*/
2126
2127                         status = winreg_del_driver(p->mem_ctx,
2128                                                    get_session_info_system(),
2129                                                    p->msg_ctx,
2130                                                    info_win2k, 3);
2131                         talloc_free(info_win2k);
2132
2133                         /* this should not have failed---if it did, report to client */
2134                         if (!W_ERROR_IS_OK(status)) {
2135                                 goto done;
2136                         }
2137                 }
2138         }
2139
2140         status = winreg_del_driver(p->mem_ctx,
2141                                    get_session_info_system(),
2142                                    p->msg_ctx,
2143                                    info, version);
2144
2145 done:
2146         talloc_free(info);
2147
2148         return status;
2149 }
2150
2151 /****************************************************************
2152  _spoolss_DeletePrinterDriverEx
2153 ****************************************************************/
2154
2155 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2156                                       struct spoolss_DeletePrinterDriverEx *r)
2157 {
2158         struct spoolss_DriverInfo8      *info = NULL;
2159         struct spoolss_DriverInfo8      *info_win2k = NULL;
2160         int                             version;
2161         bool                            delete_files;
2162         WERROR                          status;
2163
2164         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2165            and not a printer admin, then fail */
2166
2167         if ( (p->session_info->utok.uid != sec_initial_uid())
2168                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2169                 && !token_contains_name_in_list(
2170                         uidtoname(p->session_info->utok.uid),
2171                         p->session_info->info3->base.domain.string,
2172                         NULL,
2173                         p->session_info->security_token, lp_printer_admin(-1)) )
2174         {
2175                 return WERR_ACCESS_DENIED;
2176         }
2177
2178         /* check that we have a valid driver name first */
2179         if ((version = get_version_id(r->in.architecture)) == -1) {
2180                 /* this is what NT returns */
2181                 return WERR_INVALID_ENVIRONMENT;
2182         }
2183
2184         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2185                 version = r->in.version;
2186
2187         status = winreg_get_driver(p->mem_ctx,
2188                                    get_session_info_system(),
2189                                    p->msg_ctx,
2190                                    r->in.architecture,
2191                                    r->in.driver,
2192                                    version,
2193                                    &info);
2194         if (!W_ERROR_IS_OK(status)) {
2195                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2196
2197                 /*
2198                  * if the client asked for a specific version,
2199                  * or this is something other than Windows NT x86,
2200                  * then we've failed
2201                  */
2202
2203                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2204                         goto done;
2205
2206                 /* try for Win2k driver if "Windows NT x86" */
2207
2208                 version = 3;
2209                 status = winreg_get_driver(info,
2210                                            get_session_info_system(),
2211                                            p->msg_ctx,
2212                                            r->in.architecture,
2213                                            r->in.driver,
2214                                            version, &info);
2215                 if (!W_ERROR_IS_OK(status)) {
2216                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2217                         goto done;
2218                 }
2219         }
2220
2221         if (printer_driver_in_use(info,
2222                                   get_session_info_system(),
2223                                   p->msg_ctx,
2224                                   info)) {
2225                 status = WERR_PRINTER_DRIVER_IN_USE;
2226                 goto done;
2227         }
2228
2229         /*
2230          * we have a couple of cases to consider.
2231          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2232          *     then the delete should fail if **any** files overlap with
2233          *     other drivers
2234          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2235          *     non-overlapping files
2236          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2237          *     is set, the do not delete any files
2238          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2239          */
2240
2241         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2242
2243         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2244
2245         if (delete_files &&
2246             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2247             printer_driver_files_in_use(info,
2248                                         get_session_info_system(),
2249                                         p->msg_ctx,
2250                                         info)) {
2251                 /* no idea of the correct error here */
2252                 status = WERR_ACCESS_DENIED;
2253                 goto done;
2254         }
2255
2256
2257         /* also check for W32X86/3 if necessary; maybe we already have? */
2258
2259         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2260                 status = winreg_get_driver(info,
2261                                            get_session_info_system(),
2262                                            p->msg_ctx,
2263                                            r->in.architecture,
2264                                            r->in.driver, 3, &info_win2k);
2265                 if (W_ERROR_IS_OK(status)) {
2266
2267                         if (delete_files &&
2268                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2269                             printer_driver_files_in_use(info,
2270                                                         get_session_info_system(),
2271                                                         p->msg_ctx,
2272                                                         info_win2k)) {
2273                                 /* no idea of the correct error here */
2274                                 talloc_free(info_win2k);
2275                                 status = WERR_ACCESS_DENIED;
2276                                 goto done;
2277                         }
2278
2279                         /* if we get to here, we now have 2 driver info structures to remove */
2280                         /* remove the Win2k driver first*/
2281
2282                         status = winreg_del_driver(info,
2283                                                    get_session_info_system(),
2284                                                    p->msg_ctx,
2285                                                    info_win2k,
2286                                                    3);
2287
2288                         /* this should not have failed---if it did, report to client */
2289
2290                         if (!W_ERROR_IS_OK(status)) {
2291                                 goto done;
2292                         }
2293
2294                         /*
2295                          * now delete any associated files if delete_files is
2296                          * true. Even if this part failes, we return succes
2297                          * because the driver doesn not exist any more
2298                          */
2299                         if (delete_files) {
2300                                 delete_driver_files(get_session_info_system(),
2301                                                     info_win2k);
2302                         }
2303                 }
2304         }
2305
2306         status = winreg_del_driver(info,
2307                                    get_session_info_system(),
2308                                    p->msg_ctx,
2309                                    info,
2310                                    version);
2311         if (!W_ERROR_IS_OK(status)) {
2312                 goto done;
2313         }
2314
2315         /*
2316          * now delete any associated files if delete_files is
2317          * true. Even if this part failes, we return succes
2318          * because the driver doesn not exist any more
2319          */
2320         if (delete_files) {
2321                 delete_driver_files(get_session_info_system(), info);
2322         }
2323
2324 done:
2325         talloc_free(info);
2326         return status;
2327 }
2328
2329
2330 /********************************************************************
2331  GetPrinterData on a printer server Handle.
2332 ********************************************************************/
2333
2334 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2335                                             const char *value,
2336                                             enum winreg_Type *type,
2337                                             union spoolss_PrinterData *data)
2338 {
2339         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2340
2341         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2342                 *type = REG_DWORD;
2343                 data->value = 0x00;
2344                 return WERR_OK;
2345         }
2346
2347         if (!StrCaseCmp(value, "BeepEnabled")) {
2348                 *type = REG_DWORD;
2349                 data->value = 0x00;
2350                 return WERR_OK;
2351         }
2352
2353         if (!StrCaseCmp(value, "EventLog")) {
2354                 *type = REG_DWORD;
2355                 /* formally was 0x1b */
2356                 data->value = 0x00;
2357                 return WERR_OK;
2358         }
2359
2360         if (!StrCaseCmp(value, "NetPopup")) {
2361                 *type = REG_DWORD;
2362                 data->value = 0x00;
2363                 return WERR_OK;
2364         }
2365
2366         if (!StrCaseCmp(value, "MajorVersion")) {
2367                 *type = REG_DWORD;
2368
2369                 /* Windows NT 4.0 seems to not allow uploading of drivers
2370                    to a server that reports 0x3 as the MajorVersion.
2371                    need to investigate more how Win2k gets around this .
2372                    -- jerry */
2373
2374                 if (RA_WINNT == get_remote_arch()) {
2375                         data->value = 0x02;
2376                 } else {
2377                         data->value = 0x03;
2378                 }
2379
2380                 return WERR_OK;
2381         }
2382
2383         if (!StrCaseCmp(value, "MinorVersion")) {
2384                 *type = REG_DWORD;
2385                 data->value = 0x00;
2386                 return WERR_OK;
2387         }
2388
2389         /* REG_BINARY
2390          *  uint32_t size        = 0x114
2391          *  uint32_t major       = 5
2392          *  uint32_t minor       = [0|1]
2393          *  uint32_t build       = [2195|2600]
2394          *  extra unicode string = e.g. "Service Pack 3"
2395          */
2396         if (!StrCaseCmp(value, "OSVersion")) {
2397                 DATA_BLOB blob;
2398                 enum ndr_err_code ndr_err;
2399                 struct spoolss_OSVersion os;
2400
2401                 os.major                = 5;    /* Windows 2000 == 5.0 */
2402                 os.minor                = 0;
2403                 os.build                = 2195; /* build */
2404                 os.extra_string         = "";   /* leave extra string empty */
2405
2406                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2407                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2408                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2409                         return WERR_GENERAL_FAILURE;
2410                 }
2411
2412                 *type = REG_BINARY;
2413                 data->binary = blob;
2414
2415                 return WERR_OK;
2416         }
2417
2418
2419         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2420                 *type = REG_SZ;
2421
2422                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2423                 W_ERROR_HAVE_NO_MEMORY(data->string);
2424
2425                 return WERR_OK;
2426         }
2427
2428         if (!StrCaseCmp(value, "Architecture")) {
2429                 *type = REG_SZ;
2430                 data->string = talloc_strdup(mem_ctx,
2431                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2432                 W_ERROR_HAVE_NO_MEMORY(data->string);
2433
2434                 return WERR_OK;
2435         }
2436
2437         if (!StrCaseCmp(value, "DsPresent")) {
2438                 *type = REG_DWORD;
2439
2440                 /* only show the publish check box if we are a
2441                    member of a AD domain */
2442
2443                 if (lp_security() == SEC_ADS) {
2444                         data->value = 0x01;
2445                 } else {
2446                         data->value = 0x00;
2447                 }
2448                 return WERR_OK;
2449         }
2450
2451         if (!StrCaseCmp(value, "DNSMachineName")) {
2452                 const char *hostname = get_mydnsfullname();
2453
2454                 if (!hostname) {
2455                         return WERR_BADFILE;
2456                 }
2457
2458                 *type = REG_SZ;
2459                 data->string = talloc_strdup(mem_ctx, hostname);
2460                 W_ERROR_HAVE_NO_MEMORY(data->string);
2461
2462                 return WERR_OK;
2463         }
2464
2465         *type = REG_NONE;
2466
2467         return WERR_INVALID_PARAM;
2468 }
2469
2470 /****************************************************************
2471  _spoolss_GetPrinterData
2472 ****************************************************************/
2473
2474 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2475                                struct spoolss_GetPrinterData *r)
2476 {
2477         struct spoolss_GetPrinterDataEx r2;
2478
2479         r2.in.handle            = r->in.handle;
2480         r2.in.key_name          = "PrinterDriverData";
2481         r2.in.value_name        = r->in.value_name;
2482         r2.in.offered           = r->in.offered;
2483         r2.out.type             = r->out.type;
2484         r2.out.data             = r->out.data;
2485         r2.out.needed           = r->out.needed;
2486
2487         return _spoolss_GetPrinterDataEx(p, &r2);
2488 }
2489
2490 /*********************************************************
2491  Connect to the client machine.
2492 **********************************************************/
2493
2494 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2495                         struct sockaddr_storage *client_ss, const char *remote_machine)
2496 {
2497         NTSTATUS ret;
2498         struct cli_state *the_cli;
2499         struct sockaddr_storage rm_addr;
2500         char addr[INET6_ADDRSTRLEN];
2501
2502         if ( is_zero_addr(client_ss) ) {
2503                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2504                         remote_machine));
2505                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2506                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2507                         return false;
2508                 }
2509                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2510         } else {
2511                 rm_addr = *client_ss;
2512                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2513                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2514                         addr));
2515         }
2516
2517         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2518                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2519                         addr));
2520                 return false;
2521         }
2522
2523         /* setup the connection */
2524         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2525                 &rm_addr, 0, "IPC$", "IPC",
2526                 "", /* username */
2527                 "", /* domain */
2528                 "", /* password */
2529                 0, lp_client_signing());
2530
2531         if ( !NT_STATUS_IS_OK( ret ) ) {
2532                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2533                         remote_machine ));
2534                 return false;
2535         }
2536
2537         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2538                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2539                 cli_shutdown(the_cli);
2540                 return false;
2541         }
2542
2543         /*
2544          * Ok - we have an anonymous connection to the IPC$ share.
2545          * Now start the NT Domain stuff :-).
2546          */
2547
2548         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2549         if (!NT_STATUS_IS_OK(ret)) {
2550                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2551                         remote_machine, nt_errstr(ret)));
2552                 cli_shutdown(the_cli);
2553                 return false;
2554         }
2555
2556         return true;
2557 }
2558
2559 /***************************************************************************
2560  Connect to the client.
2561 ****************************************************************************/
2562
2563 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2564                                         uint32_t localprinter,
2565                                         enum winreg_Type type,
2566                                         struct policy_handle *handle,
2567                                         struct notify_back_channel **_chan,
2568                                         struct sockaddr_storage *client_ss,
2569                                         struct messaging_context *msg_ctx)
2570 {
2571         WERROR result;
2572         NTSTATUS status;
2573         struct notify_back_channel *chan;
2574
2575         for (chan = back_channels; chan; chan = chan->next) {
2576                 if (memcmp(&chan->client_address, client_ss,
2577                            sizeof(struct sockaddr_storage)) == 0) {
2578                         break;
2579                 }
2580         }
2581
2582         /*
2583          * If it's the first connection, contact the client
2584          * and connect to the IPC$ share anonymously
2585          */
2586         if (!chan) {
2587                 fstring unix_printer;
2588
2589                 /* the +2 is to strip the leading 2 backslashs */
2590                 fstrcpy(unix_printer, printer + 2);
2591
2592                 chan = talloc_zero(back_channels, struct notify_back_channel);
2593                 if (!chan) {
2594                         return false;
2595                 }
2596                 chan->client_address = *client_ss;
2597
2598                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2599                         TALLOC_FREE(chan);
2600                         return false;
2601                 }
2602                 chan->binding_handle = chan->cli_pipe->binding_handle;
2603
2604                 DLIST_ADD(back_channels, chan);
2605
2606                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2607                                    receive_notify2_message_list);
2608                 /* Tell the connections db we're now interested in printer
2609                  * notify messages. */
2610                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2611                                             true, FLAG_MSG_PRINT_NOTIFY);
2612         }
2613
2614         /*
2615          * Tell the specific printing tdb we want messages for this printer
2616          * by registering our PID.
2617          */
2618
2619         if (!print_notify_register_pid(snum)) {
2620                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2621                           printer));
2622         }
2623
2624         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2625                                                  talloc_tos(),
2626                                                  printer,
2627                                                  localprinter,
2628                                                  type,
2629                                                  0,
2630                                                  NULL,
2631                                                  handle,
2632                                                  &result);
2633         if (!NT_STATUS_IS_OK(status)) {
2634                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2635                 result = ntstatus_to_werror(status);
2636         } else if (!W_ERROR_IS_OK(result)) {
2637                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2638         }
2639
2640         chan->active_connections++;
2641         *_chan = chan;
2642
2643         return (W_ERROR_IS_OK(result));
2644 }
2645
2646 /****************************************************************
2647  ****************************************************************/
2648
2649 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2650                                                              const struct spoolss_NotifyOption *r)
2651 {
2652         struct spoolss_NotifyOption *option;
2653         uint32_t i,k;
2654
2655         if (!r) {
2656                 return NULL;
2657         }
2658
2659         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2660         if (!option) {
2661                 return NULL;
2662         }
2663
2664         *option = *r;
2665
2666         if (!option->count) {
2667                 return option;
2668         }
2669
2670         option->types = talloc_zero_array(option,
2671                 struct spoolss_NotifyOptionType, option->count);
2672         if (!option->types) {
2673                 talloc_free(option);
2674                 return NULL;
2675         }
2676
2677         for (i=0; i < option->count; i++) {
2678                 option->types[i] = r->types[i];
2679
2680                 if (option->types[i].count) {
2681                         option->types[i].fields = talloc_zero_array(option,
2682                                 union spoolss_Field, option->types[i].count);
2683                         if (!option->types[i].fields) {
2684                                 talloc_free(option);
2685                                 return NULL;
2686                         }
2687                         for (k=0; k<option->types[i].count; k++) {
2688                                 option->types[i].fields[k] =
2689                                         r->types[i].fields[k];
2690                         }
2691                 }
2692         }
2693
2694         return option;
2695 }
2696
2697 /****************************************************************
2698  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2699  *
2700  * before replying OK: status=0 a rpc call is made to the workstation
2701  * asking ReplyOpenPrinter
2702  *
2703  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2704  * called from api_spoolss_rffpcnex
2705 ****************************************************************/
2706
2707 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2708                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2709 {
2710         int snum = -1;
2711         struct spoolss_NotifyOption *option = r->in.notify_options;
2712         struct sockaddr_storage client_ss;
2713
2714         /* store the notify value in the printer struct */
2715
2716         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2717
2718         if (!Printer) {
2719                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720                         "Invalid handle (%s:%u:%u).\n",
2721                         OUR_HANDLE(r->in.handle)));
2722                 return WERR_BADFID;
2723         }
2724
2725         Printer->notify.flags           = r->in.flags;
2726         Printer->notify.options         = r->in.options;
2727         Printer->notify.printerlocal    = r->in.printer_local;
2728         Printer->notify.msg_ctx         = p->msg_ctx;
2729
2730         TALLOC_FREE(Printer->notify.option);
2731         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2732
2733         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2734
2735         /* Connect to the client machine and send a ReplyOpenPrinter */
2736
2737         if ( Printer->printer_type == SPLHND_SERVER)
2738                 snum = -1;
2739         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2740                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2741                 return WERR_BADFID;
2742
2743         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2744                 "client_address is %s\n", p->client_id->addr));
2745
2746         if (!lp_print_notify_backchannel(snum)) {
2747                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2748                         "backchannel disabled\n"));
2749                 return WERR_SERVER_UNAVAILABLE;
2750         }
2751
2752         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2753                                    AI_NUMERICHOST)) {
2754                 return WERR_SERVER_UNAVAILABLE;
2755         }
2756
2757         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2758                                         Printer->notify.printerlocal, REG_SZ,
2759                                         &Printer->notify.cli_hnd,
2760                                         &Printer->notify.cli_chan,
2761                                         &client_ss, p->msg_ctx)) {
2762                 return WERR_SERVER_UNAVAILABLE;
2763         }
2764
2765         return WERR_OK;
2766 }
2767
2768 /*******************************************************************
2769  * fill a notify_info_data with the servername
2770  ********************************************************************/
2771
2772 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2773                                        int snum,
2774                                        struct spoolss_Notify *data,
2775                                        print_queue_struct *queue,
2776                                        struct spoolss_PrinterInfo2 *pinfo2,
2777                                        TALLOC_CTX *mem_ctx)
2778 {
2779         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2780 }
2781
2782 /*******************************************************************
2783  * fill a notify_info_data with the printername (not including the servername).
2784  ********************************************************************/
2785
2786 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2787                                         int snum,
2788                                         struct spoolss_Notify *data,
2789                                         print_queue_struct *queue,
2790                                         struct spoolss_PrinterInfo2 *pinfo2,
2791                                         TALLOC_CTX *mem_ctx)
2792 {
2793         /* the notify name should not contain the \\server\ part */
2794         const char *p = strrchr(pinfo2->printername, '\\');
2795
2796         if (!p) {
2797                 p = pinfo2->printername;
2798         } else {
2799                 p++;
2800         }
2801
2802         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2803 }
2804
2805 /*******************************************************************
2806  * fill a notify_info_data with the servicename
2807  ********************************************************************/
2808
2809 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2810                                       int snum,
2811                                       struct spoolss_Notify *data,
2812                                       print_queue_struct *queue,
2813                                       struct spoolss_PrinterInfo2 *pinfo2,
2814                                       TALLOC_CTX *mem_ctx)
2815 {
2816         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2817 }
2818
2819 /*******************************************************************
2820  * fill a notify_info_data with the port name
2821  ********************************************************************/
2822
2823 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2824                                      int snum,
2825                                      struct spoolss_Notify *data,
2826                                      print_queue_struct *queue,
2827                                      struct spoolss_PrinterInfo2 *pinfo2,
2828                                      TALLOC_CTX *mem_ctx)
2829 {
2830         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2831 }
2832
2833 /*******************************************************************
2834  * fill a notify_info_data with the printername
2835  * but it doesn't exist, have to see what to do
2836  ********************************************************************/
2837
2838 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2839                                        int snum,
2840                                        struct spoolss_Notify *data,
2841                                        print_queue_struct *queue,
2842                                        struct spoolss_PrinterInfo2 *pinfo2,
2843                                        TALLOC_CTX *mem_ctx)
2844 {
2845         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2846 }
2847
2848 /*******************************************************************
2849  * fill a notify_info_data with the comment
2850  ********************************************************************/
2851
2852 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2853                                    int snum,
2854                                    struct spoolss_Notify *data,
2855                                    print_queue_struct *queue,
2856                                    struct spoolss_PrinterInfo2 *pinfo2,
2857                                    TALLOC_CTX *mem_ctx)
2858 {
2859         const char *p;
2860
2861         if (*pinfo2->comment == '\0') {
2862                 p = lp_comment(snum);
2863         } else {
2864                 p = pinfo2->comment;
2865         }
2866
2867         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2868 }
2869
2870 /*******************************************************************
2871  * fill a notify_info_data with the comment
2872  * location = "Room 1, floor 2, building 3"
2873  ********************************************************************/
2874
2875 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2876                                     int snum,
2877                                     struct spoolss_Notify *data,
2878                                     print_queue_struct *queue,
2879                                     struct spoolss_PrinterInfo2 *pinfo2,
2880                                     TALLOC_CTX *mem_ctx)
2881 {
2882         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with the device mode
2887  * jfm:xxxx don't to it for know but that's a real problem !!!
2888  ********************************************************************/
2889
2890 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2891                                    int snum,
2892                                    struct spoolss_Notify *data,
2893                                    print_queue_struct *queue,
2894                                    struct spoolss_PrinterInfo2 *pinfo2,
2895                                    TALLOC_CTX *mem_ctx)
2896 {
2897         /* for a dummy implementation we have to zero the fields */
2898         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the separator file name
2903  ********************************************************************/
2904
2905 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2906                                    int snum,
2907                                    struct spoolss_Notify *data,
2908                                    print_queue_struct *queue,
2909                                    struct spoolss_PrinterInfo2 *pinfo2,
2910                                    TALLOC_CTX *mem_ctx)
2911 {
2912         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2913 }
2914
2915 /*******************************************************************
2916  * fill a notify_info_data with the print processor
2917  * jfm:xxxx return always winprint to indicate we don't do anything to it
2918  ********************************************************************/
2919
2920 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2921                                            int snum,
2922                                            struct spoolss_Notify *data,
2923                                            print_queue_struct *queue,
2924                                            struct spoolss_PrinterInfo2 *pinfo2,
2925                                            TALLOC_CTX *mem_ctx)
2926 {
2927         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2928 }
2929
2930 /*******************************************************************
2931  * fill a notify_info_data with the print processor options
2932  * jfm:xxxx send an empty string
2933  ********************************************************************/
2934
2935 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2936                                       int snum,
2937                                       struct spoolss_Notify *data,
2938                                       print_queue_struct *queue,
2939                                       struct spoolss_PrinterInfo2 *pinfo2,
2940                                       TALLOC_CTX *mem_ctx)
2941 {
2942         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2943 }
2944
2945 /*******************************************************************
2946  * fill a notify_info_data with the data type
2947  * jfm:xxxx always send RAW as data type
2948  ********************************************************************/
2949
2950 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2951                                     int snum,
2952                                     struct spoolss_Notify *data,
2953                                     print_queue_struct *queue,
2954                                     struct spoolss_PrinterInfo2 *pinfo2,
2955                                     TALLOC_CTX *mem_ctx)
2956 {
2957         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2958 }
2959
2960 /*******************************************************************
2961  * fill a notify_info_data with the security descriptor
2962  * jfm:xxxx send an null pointer to say no security desc
2963  * have to implement security before !
2964  ********************************************************************/
2965
2966 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2967                                          int snum,
2968                                          struct spoolss_Notify *data,
2969                                          print_queue_struct *queue,
2970                                          struct spoolss_PrinterInfo2 *pinfo2,
2971                                          TALLOC_CTX *mem_ctx)
2972 {
2973         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2974 }
2975
2976 /*******************************************************************
2977  * fill a notify_info_data with the attributes
2978  * jfm:xxxx a samba printer is always shared
2979  ********************************************************************/
2980
2981 static void spoolss_notify_attributes(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->attributes);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the priority
2993  ********************************************************************/
2994
2995 static void spoolss_notify_priority(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->priority);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the default priority
3007  ********************************************************************/
3008
3009 static void spoolss_notify_default_priority(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->defaultpriority);
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the start time
3021  ********************************************************************/
3022
3023 static void spoolss_notify_start_time(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3031 }
3032
3033 /*******************************************************************
3034  * fill a notify_info_data with the until time
3035  ********************************************************************/
3036
3037 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3038                                       int snum,
3039                                       struct spoolss_Notify *data,
3040                                       print_queue_struct *queue,
3041                                       struct spoolss_PrinterInfo2 *pinfo2,
3042                                       TALLOC_CTX *mem_ctx)
3043 {
3044         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3045 }
3046
3047 /*******************************************************************
3048  * fill a notify_info_data with the status
3049  ********************************************************************/
3050
3051 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3052                                   int snum,
3053                                   struct spoolss_Notify *data,
3054                                   print_queue_struct *queue,
3055                                   struct spoolss_PrinterInfo2 *pinfo2,
3056                                   TALLOC_CTX *mem_ctx)
3057 {
3058         print_status_struct status;
3059
3060         print_queue_length(msg_ctx, snum, &status);
3061         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3062 }
3063
3064 /*******************************************************************
3065  * fill a notify_info_data with the number of jobs queued
3066  ********************************************************************/
3067
3068 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3069                                  int snum,
3070                                  struct spoolss_Notify *data,
3071                                  print_queue_struct *queue,
3072                                  struct spoolss_PrinterInfo2 *pinfo2,
3073                                  TALLOC_CTX *mem_ctx)
3074 {
3075         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3076                 data, print_queue_length(msg_ctx, snum, NULL));
3077 }
3078
3079 /*******************************************************************
3080  * fill a notify_info_data with the average ppm
3081  ********************************************************************/
3082
3083 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3084                                        int snum,
3085                                        struct spoolss_Notify *data,
3086                                        print_queue_struct *queue,
3087                                        struct spoolss_PrinterInfo2 *pinfo2,
3088                                        TALLOC_CTX *mem_ctx)
3089 {
3090         /* always respond 8 pages per minutes */
3091         /* a little hard ! */
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with username
3097  ********************************************************************/
3098
3099 static void spoolss_notify_username(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_user);
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with job status
3111  ********************************************************************/
3112
3113 static void spoolss_notify_job_status(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3121 }
3122
3123 /*******************************************************************
3124  * fill a notify_info_data with job name
3125  ********************************************************************/
3126
3127 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3128                                     int snum,
3129                                     struct spoolss_Notify *data,
3130                                     print_queue_struct *queue,
3131                                     struct spoolss_PrinterInfo2 *pinfo2,
3132                                     TALLOC_CTX *mem_ctx)
3133 {
3134         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3135 }
3136
3137 /*******************************************************************
3138  * fill a notify_info_data with job status
3139  ********************************************************************/
3140
3141 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3142                                              int snum,
3143                                              struct spoolss_Notify *data,
3144                                              print_queue_struct *queue,
3145                                              struct spoolss_PrinterInfo2 *pinfo2,
3146                                              TALLOC_CTX *mem_ctx)
3147 {
3148         /*
3149          * Now we're returning job status codes we just return a "" here. JRA.
3150          */
3151
3152         const char *p = "";
3153
3154 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3155         p = "unknown";
3156
3157         switch (queue->status) {
3158         case LPQ_QUEUED:
3159                 p = "Queued";
3160                 break;
3161         case LPQ_PAUSED:
3162                 p = "";    /* NT provides the paused string */
3163                 break;
3164         case LPQ_SPOOLING:
3165                 p = "Spooling";
3166                 break;
3167         case LPQ_PRINTING:
3168                 p = "Printing";
3169                 break;
3170         }
3171 #endif /* NO LONGER NEEDED. */
3172
3173         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with job time
3178  ********************************************************************/
3179
3180 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3181                                     int snum,
3182                                     struct spoolss_Notify *data,
3183                                     print_queue_struct *queue,
3184                                     struct spoolss_PrinterInfo2 *pinfo2,
3185                                     TALLOC_CTX *mem_ctx)
3186 {
3187         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with job size
3192  ********************************************************************/
3193
3194 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3195                                     int snum,
3196                                     struct spoolss_Notify *data,
3197                                     print_queue_struct *queue,
3198                                     struct spoolss_PrinterInfo2 *pinfo2,
3199                                     TALLOC_CTX *mem_ctx)
3200 {
3201         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3202 }
3203
3204 /*******************************************************************
3205  * fill a notify_info_data with page info
3206  ********************************************************************/
3207 static void spoolss_notify_total_pages(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->page_count);
3215 }
3216
3217 /*******************************************************************
3218  * fill a notify_info_data with pages printed info.
3219  ********************************************************************/
3220 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3221                                          int snum,
3222                                 struct spoolss_Notify *data,
3223                                 print_queue_struct *queue,
3224                                 struct spoolss_PrinterInfo2 *pinfo2,
3225                                 TALLOC_CTX *mem_ctx)
3226 {
3227         /* Add code when back-end tracks this */
3228         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3229 }
3230
3231 /*******************************************************************
3232  Fill a notify_info_data with job position.
3233  ********************************************************************/
3234
3235 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3236                                         int snum,
3237                                         struct spoolss_Notify *data,
3238                                         print_queue_struct *queue,
3239                                         struct spoolss_PrinterInfo2 *pinfo2,
3240                                         TALLOC_CTX *mem_ctx)
3241 {
3242         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3243 }
3244
3245 /*******************************************************************
3246  Fill a notify_info_data with submitted time.
3247  ********************************************************************/
3248
3249 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3250                                           int snum,
3251                                           struct spoolss_Notify *data,
3252                                           print_queue_struct *queue,
3253                                           struct spoolss_PrinterInfo2 *pinfo2,
3254                                           TALLOC_CTX *mem_ctx)
3255 {
3256         data->data.string.string = NULL;
3257         data->data.string.size = 0;
3258
3259         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3260                                &data->data.string.string,
3261                                &data->data.string.size);
3262
3263 }
3264
3265 struct s_notify_info_data_table
3266 {
3267         enum spoolss_NotifyType type;
3268         uint16_t field;
3269         const char *name;
3270         enum spoolss_NotifyTable variable_type;
3271         void (*fn) (struct messaging_context *msg_ctx,
3272                     int snum, struct spoolss_Notify *data,
3273                     print_queue_struct *queue,
3274                     struct spoolss_PrinterInfo2 *pinfo2,
3275                     TALLOC_CTX *mem_ctx);
3276 };
3277
3278 /* A table describing the various print notification constants and
3279    whether the notification data is a pointer to a variable sized
3280    buffer, a one value uint32_t or a two value uint32_t. */
3281
3282 static const struct s_notify_info_data_table notify_info_data_table[] =
3283 {
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3332 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3333 };
3334
3335 /*******************************************************************
3336  Return the variable_type of info_data structure.
3337 ********************************************************************/
3338
3339 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3340                                                                   uint16_t field)
3341 {
3342         int i=0;
3343
3344         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3345                 if ( (notify_info_data_table[i].type == type) &&
3346                      (notify_info_data_table[i].field == field) ) {
3347                         return notify_info_data_table[i].variable_type;
3348                 }
3349         }
3350
3351         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3352
3353         return (enum spoolss_NotifyTable) 0;
3354 }
3355
3356 /****************************************************************************
3357 ****************************************************************************/
3358
3359 static bool search_notify(enum spoolss_NotifyType type,
3360                           uint16_t field,
3361                           int *value)
3362 {
3363         int i;
3364
3365         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3366                 if (notify_info_data_table[i].type == type &&
3367                     notify_info_data_table[i].field == field &&
3368                     notify_info_data_table[i].fn != NULL) {
3369                         *value = i;
3370                         return true;
3371                 }
3372         }
3373
3374         return false;
3375 }
3376
3377 /****************************************************************************
3378 ****************************************************************************/
3379
3380 static void construct_info_data(struct spoolss_Notify *info_data,
3381                                 enum spoolss_NotifyType type,
3382                                 uint16_t field, int id)
3383 {
3384         info_data->type                 = type;
3385         info_data->field.field          = field;
3386         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3387         info_data->job_id               = id;
3388 }
3389
3390 /*******************************************************************
3391  *
3392  * fill a notify_info struct with info asked
3393  *
3394  ********************************************************************/
3395
3396 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3397                                           struct printer_handle *print_hnd,
3398                                           struct spoolss_NotifyInfo *info,
3399                                           struct spoolss_PrinterInfo2 *pinfo2,
3400                                           int snum,
3401                                           const struct spoolss_NotifyOptionType *option_type,
3402                                           uint32_t id,
3403                                           TALLOC_CTX *mem_ctx)
3404 {
3405         int field_num,j;
3406         enum spoolss_NotifyType type;
3407         uint16_t field;
3408
3409         struct spoolss_Notify *current_data;
3410
3411         type = option_type->type;
3412
3413         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3414                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3415                 option_type->count, lp_servicename(snum)));
3416
3417         for(field_num=0; field_num < option_type->count; field_num++) {
3418                 field = option_type->fields[field_num].field;
3419
3420                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3421
3422                 if (!search_notify(type, field, &j) )
3423                         continue;
3424
3425                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3426                                                       struct spoolss_Notify,
3427                                                       info->count + 1);
3428                 if (info->notifies == NULL) {
3429                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3430                         return false;
3431                 }
3432
3433                 current_data = &info->notifies[info->count];
3434
3435                 construct_info_data(current_data, type, field, id);
3436
3437                 DEBUG(10, ("construct_notify_printer_info: "
3438                            "calling [%s]  snum=%d  printername=[%s])\n",
3439                            notify_info_data_table[j].name, snum,
3440                            pinfo2->printername));
3441
3442                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3443                                              NULL, pinfo2, mem_ctx);
3444
3445                 info->count++;
3446         }
3447
3448         return true;
3449 }
3450
3451 /*******************************************************************
3452  *
3453  * fill a notify_info struct with info asked
3454  *
3455  ********************************************************************/
3456
3457 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3458                                        print_queue_struct *queue,
3459                                        struct spoolss_NotifyInfo *info,
3460                                        struct spoolss_PrinterInfo2 *pinfo2,
3461                                        int snum,
3462                                        const struct spoolss_NotifyOptionType *option_type,
3463                                        uint32_t id,
3464                                        TALLOC_CTX *mem_ctx)
3465 {
3466         int field_num,j;
3467         enum spoolss_NotifyType type;
3468         uint16_t field;
3469         struct spoolss_Notify *current_data;
3470
3471         DEBUG(4,("construct_notify_jobs_info\n"));
3472
3473         type = option_type->type;
3474
3475         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3476                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3477                 option_type->count));
3478
3479         for(field_num=0; field_num<option_type->count; field_num++) {
3480                 field = option_type->fields[field_num].field;
3481
3482                 if (!search_notify(type, field, &j) )
3483                         continue;
3484
3485                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3486                                                       struct spoolss_Notify,
3487                                                       info->count + 1);
3488                 if (info->notifies == NULL) {
3489                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3490                         return false;
3491                 }
3492
3493                 current_data=&(info->notifies[info->count]);
3494
3495                 construct_info_data(current_data, type, field, id);
3496                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3497                                              queue, pinfo2, mem_ctx);
3498                 info->count++;
3499         }
3500
3501         return true;
3502 }
3503
3504 /*
3505  * JFM: The enumeration is not that simple, it's even non obvious.
3506  *
3507  * let's take an example: I want to monitor the PRINTER SERVER for
3508  * the printer's name and the number of jobs currently queued.
3509  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3510  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3511  *
3512  * I have 3 printers on the back of my server.
3513  *
3514  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3515  * structures.
3516  *   Number     Data                    Id
3517  *      1       printer 1 name          1
3518  *      2       printer 1 cjob          1
3519  *      3       printer 2 name          2
3520  *      4       printer 2 cjob          2
3521  *      5       printer 3 name          3
3522  *      6       printer 3 name          3
3523  *
3524  * that's the print server case, the printer case is even worse.
3525  */
3526
3527 /*******************************************************************
3528  *
3529  * enumerate all printers on the printserver
3530  * fill a notify_info struct with info asked
3531  *
3532  ********************************************************************/
3533
3534 static WERROR printserver_notify_info(struct pipes_struct *p,
3535                                       struct policy_handle *hnd,
3536                                       struct spoolss_NotifyInfo *info,
3537                                       TALLOC_CTX *mem_ctx)
3538 {
3539         int snum;
3540         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3541         int n_services=lp_numservices();
3542         int i;
3543         struct spoolss_NotifyOption *option;
3544         struct spoolss_NotifyOptionType option_type;
3545         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3546         WERROR result;
3547
3548         DEBUG(4,("printserver_notify_info\n"));
3549
3550         if (!Printer)
3551                 return WERR_BADFID;
3552
3553         option = Printer->notify.option;
3554
3555         info->version   = 2;
3556         info->notifies  = NULL;
3557         info->count     = 0;
3558
3559         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3560            sending a ffpcn() request first */
3561
3562         if ( !option )
3563                 return WERR_BADFID;
3564
3565         for (i=0; i<option->count; i++) {
3566                 option_type = option->types[i];
3567
3568                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3569                         continue;
3570
3571                 for (snum = 0; snum < n_services; snum++) {
3572                         if (!lp_browseable(snum) ||
3573                             !lp_snum_ok(snum) ||
3574                             !lp_print_ok(snum)) {
3575                                 continue; /* skip */
3576                         }
3577
3578                         /* Maybe we should use the SYSTEM session_info here... */
3579                         result = winreg_get_printer(mem_ctx,
3580                                                     get_session_info_system(),
3581                                                     p->msg_ctx,
3582                                                     lp_servicename(snum),
3583                                                     &pinfo2);
3584                         if (!W_ERROR_IS_OK(result)) {
3585                                 DEBUG(4, ("printserver_notify_info: "
3586                                           "Failed to get printer [%s]\n",
3587                                           lp_servicename(snum)));
3588                                 continue;
3589                         }
3590
3591
3592                         construct_notify_printer_info(p->msg_ctx,
3593                                                       Printer, info,
3594                                                       pinfo2, snum,
3595                                                       &option_type, snum,
3596                                                       mem_ctx);
3597
3598                         TALLOC_FREE(pinfo2);
3599                 }
3600         }
3601
3602 #if 0
3603         /*
3604          * Debugging information, don't delete.
3605          */
3606
3607         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3608         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3609         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3610
3611         for (i=0; i<info->count; i++) {
3612                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3613                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3614                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3615         }
3616 #endif
3617
3618         return WERR_OK;
3619 }
3620
3621 /*******************************************************************
3622  *
3623  * fill a notify_info struct with info asked
3624  *
3625  ********************************************************************/
3626
3627 static WERROR printer_notify_info(struct pipes_struct *p,
3628                                   struct policy_handle *hnd,
3629                                   struct spoolss_NotifyInfo *info,
3630                                   TALLOC_CTX *mem_ctx)
3631 {
3632         int snum;
3633         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3634         int i;
3635         uint32_t id;
3636         struct spoolss_NotifyOption *option;
3637         struct spoolss_NotifyOptionType option_type;
3638         int count,j;
3639         print_queue_struct *queue=NULL;
3640         print_status_struct status;
3641         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3642         WERROR result;
3643
3644         DEBUG(4,("printer_notify_info\n"));
3645
3646         if (!Printer)
3647                 return WERR_BADFID;
3648
3649         option = Printer->notify.option;
3650         id = 0x0;
3651
3652         info->version   = 2;
3653         info->notifies  = NULL;
3654         info->count     = 0;
3655
3656         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3657            sending a ffpcn() request first */
3658
3659         if ( !option )
3660                 return WERR_BADFID;
3661
3662         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3663                 return WERR_BADFID;
3664         }
3665
3666         /* Maybe we should use the SYSTEM session_info here... */
3667         result = winreg_get_printer(mem_ctx,
3668                                     get_session_info_system(),
3669                                     p->msg_ctx,
3670                                     lp_servicename(snum), &pinfo2);
3671         if (!W_ERROR_IS_OK(result)) {
3672                 return WERR_BADFID;
3673         }
3674
3675         for (i=0; i<option->count; i++) {
3676                 option_type = option->types[i];
3677
3678                 switch (option_type.type) {
3679                 case PRINTER_NOTIFY_TYPE:
3680                         if (construct_notify_printer_info(p->msg_ctx,
3681                                                           Printer, info,
3682                                                           pinfo2, snum,
3683                                                           &option_type, id,
3684                                                           mem_ctx)) {
3685                                 id--;
3686                         }
3687                         break;
3688
3689                 case JOB_NOTIFY_TYPE:
3690
3691                         count = print_queue_status(p->msg_ctx, snum, &queue,
3692                                                    &status);
3693
3694                         for (j=0; j<count; j++) {
3695                                 construct_notify_jobs_info(p->msg_ctx,
3696                                                            &queue[j], info,
3697                                                            pinfo2, snum,
3698                                                            &option_type,
3699                                                            queue[j].job,
3700                                                            mem_ctx);
3701                         }
3702
3703                         SAFE_FREE(queue);
3704                         break;
3705                 }
3706         }
3707
3708         /*
3709          * Debugging information, don't delete.
3710          */
3711         /*
3712         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3715
3716         for (i=0; i<info->count; i++) {
3717                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3720         }
3721         */
3722
3723         talloc_free(pinfo2);
3724         return WERR_OK;
3725 }
3726
3727 /****************************************************************
3728  _spoolss_RouterRefreshPrinterChangeNotify
3729 ****************************************************************/
3730
3731 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3732                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3733 {
3734         struct spoolss_NotifyInfo *info;
3735
3736         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3737         WERROR result = WERR_BADFID;
3738
3739         /* we always have a spoolss_NotifyInfo struct */
3740         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3741         if (!info) {
3742                 result = WERR_NOMEM;
3743                 goto done;
3744         }
3745
3746         *r->out.info = info;
3747
3748         if (!Printer) {
3749                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3750                         "Invalid handle (%s:%u:%u).\n",
3751                         OUR_HANDLE(r->in.handle)));
3752                 goto done;
3753         }
3754
3755         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3756
3757         /*
3758          *      We are now using the change value, and
3759          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3760          *      I don't have a global notification system, I'm sending back all the
3761          *      information even when _NOTHING_ has changed.
3762          */
3763
3764         /* We need to keep track of the change value to send back in
3765            RRPCN replies otherwise our updates are ignored. */
3766
3767         Printer->notify.fnpcn = true;
3768
3769         if (Printer->notify.cli_chan != NULL &&
3770             Printer->notify.cli_chan->active_connections > 0) {
3771                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3772                         "Saving change value in request [%x]\n",
3773                         r->in.change_low));
3774                 Printer->notify.change = r->in.change_low;
3775         }
3776
3777         /* just ignore the spoolss_NotifyOption */
3778
3779         switch (Printer->printer_type) {
3780                 case SPLHND_SERVER:
3781                         result = printserver_notify_info(p, r->in.handle,
3782                                                          info, p->mem_ctx);
3783                         break;
3784
3785                 case SPLHND_PRINTER:
3786                         result = printer_notify_info(p, r->in.handle,
3787                                                      info, p->mem_ctx);
3788                         break;
3789         }
3790
3791         Printer->notify.fnpcn = false;
3792
3793 done:
3794         return result;
3795 }
3796
3797 /********************************************************************
3798  ********************************************************************/
3799
3800 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3801                                  const char *servername,
3802                                  const char *printername,
3803                                  const char **printername_p)
3804 {
3805         /* FIXME: add lp_force_printername() */
3806
3807         if (servername == NULL) {
3808                 *printername_p = talloc_strdup(mem_ctx, printername);
3809                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3810                 return WERR_OK;
3811         }
3812
3813         if (servername[0] == '\\' && servername[1] == '\\') {
3814                 servername += 2;
3815         }
3816
3817         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3818         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3819
3820         return WERR_OK;
3821 }
3822
3823 /********************************************************************
3824  ********************************************************************/
3825
3826 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3827                                           const char *printername)
3828 {
3829         if (dm == NULL) {
3830                 return;
3831         }
3832
3833         dm->devicename = talloc_strndup(dm, printername,
3834                                         MIN(strlen(printername), 31));
3835 }
3836
3837 /********************************************************************
3838  * construct_printer_info_0
3839  * fill a printer_info_0 struct
3840  ********************************************************************/
3841
3842 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3843                                       const struct auth_serversupplied_info *session_info,
3844                                       struct messaging_context *msg_ctx,
3845                                       struct spoolss_PrinterInfo2 *info2,
3846                                       const char *servername,
3847                                       struct spoolss_PrinterInfo0 *r,
3848                                       int snum)
3849 {
3850         int count;
3851         struct printer_session_counter *session_counter;
3852         struct timeval setuptime;
3853         print_status_struct status;
3854         WERROR result;
3855
3856         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3857         if (!W_ERROR_IS_OK(result)) {
3858                 return result;
3859         }
3860
3861         if (servername) {
3862                 r->servername = talloc_strdup(mem_ctx, servername);
3863                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3864         } else {
3865                 r->servername = NULL;
3866         }
3867
3868         count = print_queue_length(msg_ctx, snum, &status);
3869
3870         /* check if we already have a counter for this printer */
3871         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3872                 if (session_counter->snum == snum)
3873                         break;
3874         }
3875
3876         /* it's the first time, add it to the list */
3877         if (session_counter == NULL) {
3878                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3879                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3880                 session_counter->snum           = snum;
3881                 session_counter->counter        = 0;
3882                 DLIST_ADD(counter_list, session_counter);
3883         }
3884
3885         /* increment it */
3886         session_counter->counter++;
3887
3888         r->cjobs                        = count;
3889         r->total_jobs                   = 0;
3890         r->total_bytes                  = 0;
3891
3892         get_startup_time(&setuptime);
3893         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3894
3895         /* JFM:
3896          * the global_counter should be stored in a TDB as it's common to all the clients
3897          * and should be zeroed on samba startup
3898          */
3899         r->global_counter               = session_counter->counter;
3900         r->total_pages                  = 0;
3901         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3902         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3903         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3904         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3905         r->spooling                     = 0;
3906         r->max_spooling                 = 0;
3907         r->session_counter              = session_counter->counter;
3908         r->num_error_out_of_paper       = 0x0;
3909         r->num_error_not_ready          = 0x0;          /* number of print failure */
3910         r->job_error                    = 0x0;
3911         r->number_of_processors         = 0x1;
3912         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3913         r->high_part_total_bytes        = 0x0;
3914
3915         /* ChangeID in milliseconds*/
3916         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3917                                     info2->sharename, &r->change_id);
3918
3919         r->last_error                   = WERR_OK;
3920         r->status                       = nt_printq_status(status.status);
3921         r->enumerate_network_printers   = 0x0;
3922         r->c_setprinter                 = 0x0;
3923         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3924         r->processor_level              = 0x6;          /* 6  ???*/
3925         r->ref_ic                       = 0;
3926         r->reserved2                    = 0;
3927         r->reserved3                    = 0;
3928
3929         return WERR_OK;
3930 }
3931
3932
3933 /********************************************************************
3934  * construct_printer_info1
3935  * fill a spoolss_PrinterInfo1 struct
3936 ********************************************************************/
3937
3938 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3939                                       const struct spoolss_PrinterInfo2 *info2,
3940                                       uint32_t flags,
3941                                       const char *servername,
3942                                       struct spoolss_PrinterInfo1 *r,
3943                                       int snum)
3944 {
3945         WERROR result;
3946
3947         r->flags                = flags;
3948
3949         if (info2->comment == NULL || info2->comment[0] == '\0') {
3950                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3951         } else {
3952                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3953         }
3954         W_ERROR_HAVE_NO_MEMORY(r->comment);
3955
3956         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3957         if (!W_ERROR_IS_OK(result)) {
3958                 return result;
3959         }
3960
3961         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3962                                                   r->name,
3963                                                   info2->drivername,
3964                                                   r->comment);
3965         W_ERROR_HAVE_NO_MEMORY(r->description);
3966
3967         return WERR_OK;
3968 }
3969
3970 /********************************************************************
3971  * construct_printer_info2
3972  * fill a spoolss_PrinterInfo2 struct
3973 ********************************************************************/
3974
3975 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3976                                       struct messaging_context *msg_ctx,
3977                                       const struct spoolss_PrinterInfo2 *info2,
3978                                       const char *servername,
3979                                       struct spoolss_PrinterInfo2 *r,
3980                                       int snum)
3981 {
3982         int count;
3983         print_status_struct status;
3984         WERROR result;
3985
3986         count = print_queue_length(msg_ctx, snum, &status);
3987
3988         if (servername) {
3989                 r->servername           = talloc_strdup(mem_ctx, servername);
3990                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3991         } else {
3992                 r->servername           = NULL;
3993         }
3994
3995         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3996         if (!W_ERROR_IS_OK(result)) {
3997                 return result;
3998         }
3999
4000         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4001         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4002         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4003         W_ERROR_HAVE_NO_MEMORY(r->portname);
4004         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4005         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4006
4007         if (info2->comment[0] == '\0') {
4008                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4009         } else {
4010                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4011         }
4012         W_ERROR_HAVE_NO_MEMORY(r->comment);
4013
4014         r->location             = talloc_strdup(mem_ctx, info2->location);
4015         W_ERROR_HAVE_NO_MEMORY(r->location);
4016         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4017         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4018         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4019         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4020         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4021         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4022         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4023         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4024
4025         r->attributes           = info2->attributes;
4026
4027         r->priority             = info2->priority;
4028         r->defaultpriority      = info2->defaultpriority;
4029         r->starttime            = info2->starttime;
4030         r->untiltime            = info2->untiltime;
4031         r->status               = nt_printq_status(status.status);
4032         r->cjobs                = count;
4033         r->averageppm           = info2->averageppm;
4034
4035         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4036         if (!r->devmode) {
4037                 DEBUG(8,("Returning NULL Devicemode!\n"));
4038         }
4039
4040         compose_devicemode_devicename(r->devmode, r->printername);
4041
4042         r->secdesc = NULL;
4043
4044         if (info2->secdesc != NULL) {
4045                 /* don't use talloc_steal() here unless you do a deep steal of all
4046                    the SEC_DESC members */
4047
4048                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4049         }
4050
4051         return WERR_OK;
4052 }
4053
4054 /********************************************************************
4055  * construct_printer_info3
4056  * fill a spoolss_PrinterInfo3 struct
4057  ********************************************************************/
4058
4059 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4060                                       const struct spoolss_PrinterInfo2 *info2,
4061                                       const char *servername,
4062                                       struct spoolss_PrinterInfo3 *r,
4063                                       int snum)
4064 {
4065         /* These are the components of the SD we are returning. */
4066
4067         if (info2->secdesc != NULL) {
4068                 /* don't use talloc_steal() here unless you do a deep steal of all
4069                    the SEC_DESC members */
4070
4071                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4072                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4073         }
4074
4075         return WERR_OK;
4076 }
4077
4078 /********************************************************************
4079  * construct_printer_info4
4080  * fill a spoolss_PrinterInfo4 struct
4081  ********************************************************************/
4082
4083 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4084                                       const struct spoolss_PrinterInfo2 *info2,
4085                                       const char *servername,
4086                                       struct spoolss_PrinterInfo4 *r,
4087                                       int snum)
4088 {
4089         WERROR result;
4090
4091         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4092         if (!W_ERROR_IS_OK(result)) {
4093                 return result;
4094         }
4095
4096         if (servername) {
4097                 r->servername   = talloc_strdup(mem_ctx, servername);
4098                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4099         } else {
4100                 r->servername = NULL;
4101         }
4102
4103         r->attributes   = info2->attributes;
4104
4105         return WERR_OK;
4106 }
4107
4108 /********************************************************************
4109  * construct_printer_info5
4110  * fill a spoolss_PrinterInfo5 struct
4111  ********************************************************************/
4112
4113 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4114                                       const struct spoolss_PrinterInfo2 *info2,
4115                                       const char *servername,
4116                                       struct spoolss_PrinterInfo5 *r,
4117                                       int snum)
4118 {
4119         WERROR result;
4120
4121         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4122         if (!W_ERROR_IS_OK(result)) {
4123                 return result;
4124         }
4125
4126         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4127         W_ERROR_HAVE_NO_MEMORY(r->portname);
4128
4129         r->attributes   = info2->attributes;
4130
4131         /* these two are not used by NT+ according to MSDN */
4132         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4133         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4134
4135         return WERR_OK;
4136 }
4137
4138 /********************************************************************
4139  * construct_printer_info_6
4140  * fill a spoolss_PrinterInfo6 struct
4141  ********************************************************************/
4142
4143 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4144                                       struct messaging_context *msg_ctx,
4145                                       const struct spoolss_PrinterInfo2 *info2,
4146                                       const char *servername,
4147                                       struct spoolss_PrinterInfo6 *r,
4148                                       int snum)
4149 {
4150         int count;
4151         print_status_struct status;
4152
4153         count = print_queue_length(msg_ctx, snum, &status);
4154
4155         r->status = nt_printq_status(status.status);
4156
4157         return WERR_OK;
4158 }
4159
4160 /********************************************************************
4161  * construct_printer_info7
4162  * fill a spoolss_PrinterInfo7 struct
4163  ********************************************************************/
4164
4165 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4166                                       struct messaging_context *msg_ctx,
4167                                       const char *servername,
4168                                       struct spoolss_PrinterInfo7 *r,
4169                                       int snum)
4170 {
4171         struct auth_serversupplied_info *session_info;
4172         struct GUID guid;
4173         NTSTATUS status;
4174
4175         status = make_session_info_system(mem_ctx, &session_info);
4176         if (!NT_STATUS_IS_OK(status)) {
4177                 DEBUG(0, ("construct_printer_info7: "
4178                           "Could not create system session_info\n"));
4179                 return WERR_NOMEM;
4180         }
4181
4182         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4183                                  servername,
4184                                  lp_servicename(snum), &guid, NULL)) {
4185                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4186                 r->action = DSPRINT_PUBLISH;
4187         } else {
4188                 r->guid = talloc_strdup(mem_ctx, "");
4189                 r->action = DSPRINT_UNPUBLISH;
4190         }
4191         W_ERROR_HAVE_NO_MEMORY(r->guid);
4192
4193         TALLOC_FREE(session_info);
4194         return WERR_OK;
4195 }
4196
4197 /********************************************************************
4198  * construct_printer_info8
4199  * fill a spoolss_PrinterInfo8 struct
4200  ********************************************************************/
4201
4202 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4203                                       const struct spoolss_PrinterInfo2 *info2,
4204                                       const char *servername,
4205                                       struct spoolss_DeviceModeInfo *r,
4206                                       int snum)
4207 {
4208         WERROR result;
4209         const char *printername;
4210
4211         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4212         if (!W_ERROR_IS_OK(result)) {
4213                 return result;
4214         }
4215
4216         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4217         if (!r->devmode) {
4218                 DEBUG(8,("Returning NULL Devicemode!\n"));
4219         }
4220
4221         compose_devicemode_devicename(r->devmode, printername);
4222
4223         return WERR_OK;
4224 }
4225
4226
4227 /********************************************************************
4228 ********************************************************************/
4229
4230 static bool snum_is_shared_printer(int snum)
4231 {
4232         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4233 }
4234
4235 /********************************************************************
4236  Spoolss_enumprinters.
4237 ********************************************************************/
4238
4239 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4240                                            const struct auth_serversupplied_info *session_info,
4241                                            struct messaging_context *msg_ctx,
4242                                            const char *servername,
4243                                            uint32_t level,
4244                                            uint32_t flags,
4245                                            union spoolss_PrinterInfo **info_p,
4246                                            uint32_t *count_p)
4247 {
4248         int snum;
4249         int n_services = lp_numservices();
4250         union spoolss_PrinterInfo *info = NULL;
4251         uint32_t count = 0;
4252         WERROR result = WERR_OK;
4253
4254         *count_p = 0;
4255         *info_p = NULL;
4256
4257         for (snum = 0; snum < n_services; snum++) {
4258
4259                 const char *printer;
4260                 struct spoolss_PrinterInfo2 *info2;
4261
4262                 if (!snum_is_shared_printer(snum)) {
4263                         continue;
4264                 }
4265
4266                 printer = lp_const_servicename(snum);
4267
4268                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4269                         printer, snum));
4270
4271                 result = winreg_create_printer(mem_ctx,
4272                                                session_info,
4273                                                msg_ctx,
4274                                                printer);
4275                 if (!W_ERROR_IS_OK(result)) {
4276                         goto out;
4277                 }
4278
4279                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4280                                             union spoolss_PrinterInfo,
4281                                             count + 1);
4282                 if (!info) {
4283                         result = WERR_NOMEM;
4284                         goto out;
4285                 }
4286
4287                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4288                                             printer, &info2);
4289                 if (!W_ERROR_IS_OK(result)) {
4290                         goto out;
4291                 }
4292
4293                 switch (level) {
4294                 case 0:
4295                         result = construct_printer_info0(info, session_info,
4296                                                          msg_ctx, info2,
4297                                                          servername,
4298                                                          &info[count].info0, snum);
4299                         break;
4300                 case 1:
4301                         result = construct_printer_info1(info, info2, flags,
4302                                                          servername,
4303                                                          &info[count].info1, snum);
4304                         break;
4305                 case 2:
4306                         result = construct_printer_info2(info, msg_ctx, info2,
4307                                                          servername,
4308                                                          &info[count].info2, snum);
4309                         break;
4310                 case 4:
4311                         result = construct_printer_info4(info, info2,
4312                                                          servername,
4313                                                          &info[count].info4, snum);
4314                         break;
4315                 case 5:
4316                         result = construct_printer_info5(info, info2,
4317                                                          servername,
4318                                                          &info[count].info5, snum);
4319                         break;
4320
4321                 default:
4322                         result = WERR_UNKNOWN_LEVEL;
4323                         goto out;
4324                 }
4325
4326                 if (!W_ERROR_IS_OK(result)) {
4327                         goto out;
4328                 }
4329
4330                 count++;
4331         }
4332
4333         *count_p = count;
4334         *info_p = info;
4335
4336  out:
4337         if (!W_ERROR_IS_OK(result)) {
4338                 TALLOC_FREE(info);
4339                 return result;
4340         }
4341
4342         *info_p = info;
4343
4344         return WERR_OK;
4345 }
4346
4347 /********************************************************************
4348  * handle enumeration of printers at level 0
4349  ********************************************************************/
4350
4351 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4352                                   const struct auth_serversupplied_info *session_info,
4353                                   struct messaging_context *msg_ctx,
4354                                   uint32_t flags,
4355                                   const char *servername,
4356                                   union spoolss_PrinterInfo **info,
4357                                   uint32_t *count)
4358 {
4359         DEBUG(4,("enum_all_printers_info_0\n"));
4360
4361         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4362                                             servername, 0, flags, info, count);
4363 }
4364
4365
4366 /********************************************************************
4367 ********************************************************************/
4368
4369 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4370                                        const struct auth_serversupplied_info *session_info,
4371                                        struct messaging_context *msg_ctx,
4372                                        const char *servername,
4373                                        uint32_t flags,
4374                                        union spoolss_PrinterInfo **info,
4375                                        uint32_t *count)
4376 {
4377         DEBUG(4,("enum_all_printers_info_1\n"));
4378
4379         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380                                             servername, 1, flags, info, count);
4381 }
4382
4383 /********************************************************************
4384  enum_all_printers_info_1_local.
4385 *********************************************************************/
4386
4387 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4388                                              const struct auth_serversupplied_info *session_info,
4389                                              struct messaging_context *msg_ctx,
4390                                              const char *servername,
4391                                              union spoolss_PrinterInfo **info,
4392                                              uint32_t *count)
4393 {
4394         DEBUG(4,("enum_all_printers_info_1_local\n"));
4395
4396         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4397                                         servername, PRINTER_ENUM_ICON8, info, count);
4398 }
4399
4400 /********************************************************************
4401  enum_all_printers_info_1_name.
4402 *********************************************************************/
4403
4404 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4405                                             const struct auth_serversupplied_info *session_info,
4406                                             struct messaging_context *msg_ctx,
4407                                             const char *servername,
4408                                             union spoolss_PrinterInfo **info,
4409                                             uint32_t *count)
4410 {
4411         const char *s = servername;
4412
4413         DEBUG(4,("enum_all_printers_info_1_name\n"));
4414
4415         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4416                 s = servername + 2;
4417         }
4418
4419         if (!is_myname_or_ipaddr(s)) {
4420                 return WERR_INVALID_NAME;
4421         }
4422
4423         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4424                                         servername, PRINTER_ENUM_ICON8, info, count);
4425 }
4426
4427 /********************************************************************
4428  enum_all_printers_info_1_network.
4429 *********************************************************************/
4430
4431 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4432                                                const struct auth_serversupplied_info *session_info,
4433                                                struct messaging_context *msg_ctx,
4434                                                const char *servername,
4435                                                union spoolss_PrinterInfo **info,
4436                                                uint32_t *count)
4437 {
4438         const char *s = servername;
4439
4440         DEBUG(4,("enum_all_printers_info_1_network\n"));
4441
4442         /* If we respond to a enum_printers level 1 on our name with flags
4443            set to PRINTER_ENUM_REMOTE with a list of printers then these
4444            printers incorrectly appear in the APW browse list.
4445            Specifically the printers for the server appear at the workgroup
4446            level where all the other servers in the domain are
4447            listed. Windows responds to this call with a
4448            WERR_CAN_NOT_COMPLETE so we should do the same. */
4449
4450         if (servername[0] == '\\' && servername[1] == '\\') {
4451                  s = servername + 2;
4452         }
4453
4454         if (is_myname_or_ipaddr(s)) {
4455                  return WERR_CAN_NOT_COMPLETE;
4456         }
4457
4458         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4459                                         servername, PRINTER_ENUM_NAME, info, count);
4460 }
4461
4462 /********************************************************************
4463  * api_spoolss_enumprinters
4464  *
4465  * called from api_spoolss_enumprinters (see this to understand)
4466  ********************************************************************/
4467
4468 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4469                                        const struct auth_serversupplied_info *session_info,
4470                                        struct messaging_context *msg_ctx,
4471                                        const char *servername,
4472                                        union spoolss_PrinterInfo **info,
4473                                        uint32_t *count)
4474 {
4475         DEBUG(4,("enum_all_printers_info_2\n"));
4476
4477         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4478                                             servername, 2, 0, info, count);
4479 }
4480
4481 /********************************************************************
4482  * handle enumeration of printers at level 1
4483  ********************************************************************/
4484
4485 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4486                                   const struct auth_serversupplied_info *session_info,
4487                                   struct messaging_context *msg_ctx,
4488                                   uint32_t flags,
4489                                   const char *servername,
4490                                   union spoolss_PrinterInfo **info,
4491                                   uint32_t *count)
4492 {
4493         /* Not all the flags are equals */
4494
4495         if (flags & PRINTER_ENUM_LOCAL) {
4496                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4497                                                       msg_ctx, servername, info, count);
4498         }
4499
4500         if (flags & PRINTER_ENUM_NAME) {
4501                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4502                                                      msg_ctx, servername, info,
4503                                                      count);
4504         }
4505
4506         if (flags & PRINTER_ENUM_NETWORK) {
4507                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4508                                                         msg_ctx, servername, info,
4509                                                         count);
4510         }
4511
4512         return WERR_OK; /* NT4sp5 does that */
4513 }
4514
4515 /********************************************************************
4516  * handle enumeration of printers at level 2
4517  ********************************************************************/
4518
4519 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4520                                   const struct auth_serversupplied_info *session_info,
4521                                   struct messaging_context *msg_ctx,
4522                                   uint32_t flags,
4523                                   const char *servername,
4524                                   union spoolss_PrinterInfo **info,
4525                                   uint32_t *count)
4526 {
4527         if (flags & PRINTER_ENUM_LOCAL) {
4528
4529                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4530                                                 servername,
4531                                                 info, count);
4532         }
4533
4534         if (flags & PRINTER_ENUM_NAME) {
4535                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4536                         return WERR_INVALID_NAME;
4537                 }
4538
4539                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4540                                                 servername,
4541                                                 info, count);
4542         }
4543
4544         if (flags & PRINTER_ENUM_REMOTE) {
4545                 return WERR_UNKNOWN_LEVEL;
4546         }
4547
4548         return WERR_OK;
4549 }
4550
4551 /********************************************************************
4552  * handle enumeration of printers at level 4
4553  ********************************************************************/
4554
4555 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4556                                   const struct auth_serversupplied_info *session_info,
4557                                   struct messaging_context *msg_ctx,
4558                                   uint32_t flags,
4559                                   const char *servername,
4560                                   union spoolss_PrinterInfo **info,
4561                                   uint32_t *count)
4562 {
4563         DEBUG(4,("enum_all_printers_info_4\n"));
4564
4565         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4566                                             servername, 4, flags, info, count);
4567 }
4568
4569
4570 /********************************************************************
4571  * handle enumeration of printers at level 5
4572  ********************************************************************/
4573
4574 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4575                                   const struct auth_serversupplied_info *session_info,
4576                                   struct messaging_context *msg_ctx,
4577                                   uint32_t flags,
4578                                   const char *servername,
4579                                   union spoolss_PrinterInfo **info,
4580                                   uint32_t *count)
4581 {
4582         DEBUG(4,("enum_all_printers_info_5\n"));
4583
4584         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585                                             servername, 5, flags, info, count);
4586 }
4587
4588 /****************************************************************
4589  _spoolss_EnumPrinters
4590 ****************************************************************/
4591
4592 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4593                              struct spoolss_EnumPrinters *r)
4594 {
4595         const struct auth_serversupplied_info *session_info = get_session_info_system();
4596         WERROR result;
4597
4598         /* that's an [in out] buffer */
4599
4600         if (!r->in.buffer && (r->in.offered != 0)) {
4601                 return WERR_INVALID_PARAM;
4602         }
4603
4604         DEBUG(4,("_spoolss_EnumPrinters\n"));
4605
4606         *r->out.needed = 0;
4607         *r->out.count = 0;
4608         *r->out.info = NULL;
4609
4610         /*
4611          * Level 1:
4612          *          flags==PRINTER_ENUM_NAME
4613          *           if name=="" then enumerates all printers
4614          *           if name!="" then enumerate the printer
4615          *          flags==PRINTER_ENUM_REMOTE
4616          *          name is NULL, enumerate printers
4617          * Level 2: name!="" enumerates printers, name can't be NULL
4618          * Level 3: doesn't exist
4619          * Level 4: does a local registry lookup
4620          * Level 5: same as Level 2
4621          */
4622
4623         if (r->in.server && r->in.server[0] == '\0') {
4624                 r->in.server = NULL;
4625         }
4626
4627         switch (r->in.level) {
4628         case 0:
4629                 result = enumprinters_level0(p->mem_ctx, session_info,
4630                                              p->msg_ctx, r->in.flags,
4631                                              r->in.server,
4632                                              r->out.info, r->out.count);
4633                 break;
4634         case 1:
4635                 result = enumprinters_level1(p->mem_ctx, session_info,
4636                                              p->msg_ctx, r->in.flags,
4637                                              r->in.server,
4638                                              r->out.info, r->out.count);
4639                 break;
4640         case 2:
4641                 result = enumprinters_level2(p->mem_ctx, session_info,
4642                                              p->msg_ctx, r->in.flags,
4643                                              r->in.server,
4644                                              r->out.info, r->out.count);
4645                 break;
4646         case 4:
4647                 result = enumprinters_level4(p->mem_ctx, session_info,
4648                                              p->msg_ctx, r->in.flags,
4649                                              r->in.server,
4650                                              r->out.info, r->out.count);
4651                 break;
4652         case 5:
4653                 result = enumprinters_level5(p->mem_ctx, session_info,
4654                                              p->msg_ctx, r->in.flags,
4655                                              r->in.server,
4656                                              r->out.info, r->out.count);
4657                 break;
4658         default:
4659                 return WERR_UNKNOWN_LEVEL;
4660         }
4661
4662         if (!W_ERROR_IS_OK(result)) {
4663                 return result;
4664         }
4665
4666         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4667                                                      spoolss_EnumPrinters,
4668                                                      *r->out.info, r->in.level,
4669                                                      *r->out.count);
4670         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4671         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4672
4673         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4674 }
4675
4676 /****************************************************************
4677  _spoolss_GetPrinter
4678 ****************************************************************/
4679
4680 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4681                            struct spoolss_GetPrinter *r)
4682 {
4683         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4684         struct spoolss_PrinterInfo2 *info2 = NULL;
4685         WERROR result = WERR_OK;
4686         int snum;
4687
4688         /* that's an [in out] buffer */
4689
4690         if (!r->in.buffer && (r->in.offered != 0)) {
4691                 return WERR_INVALID_PARAM;
4692         }
4693
4694         *r->out.needed = 0;
4695
4696         if (Printer == NULL) {
4697                 return WERR_BADFID;
4698         }
4699
4700         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4701                 return WERR_BADFID;
4702         }
4703
4704         result = winreg_get_printer(p->mem_ctx,
4705                                     get_session_info_system(),
4706                                     p->msg_ctx,
4707                                     lp_const_servicename(snum),
4708                                     &info2);
4709         if (!W_ERROR_IS_OK(result)) {
4710                 goto out;
4711         }
4712
4713         switch (r->in.level) {
4714         case 0:
4715                 result = construct_printer_info0(p->mem_ctx,
4716                                                  get_session_info_system(),
4717                                                  p->msg_ctx,
4718                                                  info2,
4719                                                  Printer->servername,
4720                                                  &r->out.info->info0,
4721                                                  snum);
4722                 break;
4723         case 1:
4724                 result = construct_printer_info1(p->mem_ctx, info2,
4725                                                  PRINTER_ENUM_ICON8,
4726                                                  Printer->servername,
4727                                                  &r->out.info->info1, snum);
4728                 break;
4729         case 2:
4730                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4731                                                  Printer->servername,
4732                                                  &r->out.info->info2, snum);
4733                 break;
4734         case 3:
4735                 result = construct_printer_info3(p->mem_ctx, info2,
4736                                                  Printer->servername,
4737                                                  &r->out.info->info3, snum);
4738                 break;
4739         case 4:
4740                 result = construct_printer_info4(p->mem_ctx, info2,
4741                                                  Printer->servername,
4742                                                  &r->out.info->info4, snum);
4743                 break;
4744         case 5:
4745                 result = construct_printer_info5(p->mem_ctx, info2,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info5, snum);
4748                 break;
4749         case 6:
4750                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info6, snum);
4753                 break;
4754         case 7:
4755                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4756                                                  Printer->servername,
4757                                                  &r->out.info->info7, snum);
4758                 break;
4759         case 8:
4760                 result = construct_printer_info8(p->mem_ctx, info2,
4761                                                  Printer->servername,
4762                                                  &r->out.info->info8, snum);
4763                 break;
4764         default:
4765                 result = WERR_UNKNOWN_LEVEL;
4766                 break;
4767         }
4768
4769  out:
4770         if (!W_ERROR_IS_OK(result)) {
4771                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4772                           r->in.level, win_errstr(result)));
4773                 TALLOC_FREE(r->out.info);
4774                 return result;
4775         }
4776
4777         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4778                                                r->out.info, r->in.level);
4779         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4780
4781         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4782 }
4783
4784 /********************************************************************
4785  ********************************************************************/
4786
4787 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4788         do { \
4789                 if (in && strlen(in)) { \
4790                         out = talloc_strdup(mem_ctx, in); \
4791                 } else { \
4792                         out = talloc_strdup(mem_ctx, ""); \
4793                 } \
4794                 W_ERROR_HAVE_NO_MEMORY(out); \
4795         } while (0);
4796
4797 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4798         do { \
4799                 if (in && strlen(in)) { \
4800                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4801                 } else { \
4802                         out = talloc_strdup(mem_ctx, ""); \
4803                 } \
4804                 W_ERROR_HAVE_NO_MEMORY(out); \
4805         } while (0);
4806
4807 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4808                                                   const char **string_array,
4809                                                   const char ***presult,
4810                                                   const char *cservername,
4811                                                   const char *arch,
4812                                                   int version)
4813 {
4814         int i, num_strings = 0;
4815         const char **array = NULL;
4816
4817         if (string_array == NULL) {
4818                 return WERR_INVALID_PARAMETER;
4819         }
4820
4821         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4822                 const char *str = NULL;
4823
4824                 if (cservername == NULL || arch == NULL) {
4825                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4826                 } else {
4827                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4828                 }
4829
4830                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4831                         TALLOC_FREE(array);
4832                         return WERR_NOMEM;
4833                 }
4834         }
4835
4836         if (i > 0) {
4837                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4838                              &array, &num_strings);
4839         }
4840
4841         if (presult) {
4842                 *presult = array;
4843         }
4844
4845         return WERR_OK;
4846 }
4847
4848 /********************************************************************
4849  * fill a spoolss_DriverInfo1 struct
4850  ********************************************************************/
4851
4852 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4853                                         struct spoolss_DriverInfo1 *r,
4854                                         const struct spoolss_DriverInfo8 *driver,
4855                                         const char *servername)
4856 {
4857         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4858         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4859
4860         return WERR_OK;
4861 }
4862
4863 /********************************************************************
4864  * fill a spoolss_DriverInfo2 struct
4865  ********************************************************************/
4866
4867 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4868                                         struct spoolss_DriverInfo2 *r,
4869                                         const struct spoolss_DriverInfo8 *driver,
4870                                         const char *servername)
4871
4872 {
4873         const char *cservername = canon_servername(servername);
4874
4875         r->version              = driver->version;
4876
4877         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4878         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4879         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4880         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4881
4882         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4883                                driver->architecture,
4884                                driver->version,
4885                                driver->driver_path,
4886                                r->driver_path);
4887
4888         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4889                                driver->architecture,
4890                                driver->version,
4891                                driver->data_file,
4892                                r->data_file);
4893
4894         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4895                                driver->architecture,
4896                                driver->version,
4897                                driver->config_file,
4898                                r->config_file);
4899
4900         return WERR_OK;
4901 }
4902
4903 /********************************************************************
4904  * fill a spoolss_DriverInfo3 struct
4905  ********************************************************************/
4906
4907 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4908                                         struct spoolss_DriverInfo3 *r,
4909                                         const struct spoolss_DriverInfo8 *driver,
4910                                         const char *servername)
4911 {
4912         const char *cservername = canon_servername(servername);
4913
4914         r->version              = driver->version;
4915
4916         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4917         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4918         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4919         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4920
4921         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4922                                driver->architecture,
4923                                driver->version,
4924                                driver->driver_path,
4925                                r->driver_path);
4926
4927         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4928                                driver->architecture,
4929                                driver->version,
4930                                driver->data_file,
4931                                r->data_file);
4932
4933         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4934                                driver->architecture,
4935                                driver->version,
4936                                driver->config_file,
4937                                r->config_file);
4938
4939         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940                                driver->architecture,
4941                                driver->version,
4942                                driver->help_file,
4943                                r->help_file);
4944
4945         FILL_DRIVER_STRING(mem_ctx,
4946                            driver->monitor_name,
4947                            r->monitor_name);
4948
4949         FILL_DRIVER_STRING(mem_ctx,
4950                            driver->default_datatype,
4951                            r->default_datatype);
4952
4953         return string_array_from_driver_info(mem_ctx,
4954                                              driver->dependent_files,
4955                                              &r->dependent_files,
4956                                              cservername,
4957                                              driver->architecture,
4958                                              driver->version);
4959 }
4960
4961 /********************************************************************
4962  * fill a spoolss_DriverInfo4 struct
4963  ********************************************************************/
4964
4965 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4966                                         struct spoolss_DriverInfo4 *r,
4967                                         const struct spoolss_DriverInfo8 *driver,
4968                                         const char *servername)
4969 {
4970         const char *cservername = canon_servername(servername);
4971         WERROR result;
4972
4973         r->version              = driver->version;
4974
4975         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4976         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4977         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4978         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4979
4980         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4981                                driver->architecture,
4982                                driver->version,
4983                                driver->driver_path,
4984                                r->driver_path);
4985
4986         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4987                                driver->architecture,
4988                                driver->version,
4989                                driver->data_file,
4990                                r->data_file);
4991
4992         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993                                driver->architecture,
4994                                driver->version,
4995                                driver->config_file,
4996                                r->config_file);
4997
4998         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999                                driver->architecture,
5000                                driver->version,
5001                                driver->help_file,
5002                                r->help_file);
5003
5004         result = string_array_from_driver_info(mem_ctx,
5005                                                driver->dependent_files,
5006                                                &r->dependent_files,
5007                                                cservername,
5008                                                driver->architecture,
5009                                                driver->version);
5010         if (!W_ERROR_IS_OK(result)) {
5011                 return result;
5012         }
5013
5014         FILL_DRIVER_STRING(mem_ctx,
5015                            driver->monitor_name,
5016                            r->monitor_name);
5017
5018         FILL_DRIVER_STRING(mem_ctx,
5019                            driver->default_datatype,
5020                            r->default_datatype);
5021
5022
5023         result = string_array_from_driver_info(mem_ctx,
5024                                                driver->previous_names,
5025                                                &r->previous_names,
5026                                                NULL, NULL, 0);
5027
5028         return result;
5029 }
5030
5031 /********************************************************************
5032  * fill a spoolss_DriverInfo5 struct
5033  ********************************************************************/
5034
5035 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5036                                         struct spoolss_DriverInfo5 *r,
5037                                         const struct spoolss_DriverInfo8 *driver,
5038                                         const char *servername)
5039 {
5040         const char *cservername = canon_servername(servername);
5041
5042         r->version              = driver->version;
5043
5044         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5045         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5046         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5047         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5048
5049         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050                                driver->architecture,
5051                                driver->version,
5052                                driver->driver_path,
5053                                r->driver_path);
5054
5055         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056                                driver->architecture,
5057                                driver->version,
5058                                driver->data_file,
5059                                r->data_file);
5060
5061         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5062                                driver->architecture,
5063                                driver->version,
5064                                driver->config_file,
5065                                r->config_file);
5066
5067         r->driver_attributes    = 0;
5068         r->config_version       = 0;
5069         r->driver_version       = 0;
5070
5071         return WERR_OK;
5072 }
5073 /********************************************************************
5074  * fill a spoolss_DriverInfo6 struct
5075  ********************************************************************/
5076
5077 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5078                                         struct spoolss_DriverInfo6 *r,
5079                                         const struct spoolss_DriverInfo8 *driver,
5080                                         const char *servername)
5081 {
5082         const char *cservername = canon_servername(servername);
5083         WERROR result;
5084
5085         r->version              = driver->version;
5086
5087         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5088         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5089         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5090         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5091
5092         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093                                driver->architecture,
5094                                driver->version,
5095                                driver->driver_path,
5096                                r->driver_path);
5097
5098         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099                                driver->architecture,
5100                                driver->version,
5101                                driver->data_file,
5102                                r->data_file);
5103
5104         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105                                driver->architecture,
5106                                driver->version,
5107                                driver->config_file,
5108                                r->config_file);
5109
5110         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111                                driver->architecture,
5112                                driver->version,
5113                                driver->help_file,
5114                                r->help_file);
5115
5116         FILL_DRIVER_STRING(mem_ctx,
5117                            driver->monitor_name,
5118                            r->monitor_name);
5119
5120         FILL_DRIVER_STRING(mem_ctx,
5121                            driver->default_datatype,
5122                            r->default_datatype);
5123
5124         result = string_array_from_driver_info(mem_ctx,
5125                                                driver->dependent_files,
5126                                                &r->dependent_files,
5127                                                cservername,
5128                                                driver->architecture,
5129                                                driver->version);
5130         if (!W_ERROR_IS_OK(result)) {
5131                 return result;
5132         }
5133
5134         result = string_array_from_driver_info(mem_ctx,
5135                                                driver->previous_names,
5136                                                &r->previous_names,
5137                                                NULL, NULL, 0);
5138         if (!W_ERROR_IS_OK(result)) {
5139                 return result;
5140         }
5141
5142         r->driver_date          = driver->driver_date;
5143         r->driver_version       = driver->driver_version;
5144
5145         FILL_DRIVER_STRING(mem_ctx,
5146                            driver->manufacturer_name,
5147                            r->manufacturer_name);
5148         FILL_DRIVER_STRING(mem_ctx,
5149                            driver->manufacturer_url,
5150                            r->manufacturer_url);
5151         FILL_DRIVER_STRING(mem_ctx,
5152                            driver->hardware_id,
5153                            r->hardware_id);
5154         FILL_DRIVER_STRING(mem_ctx,
5155                            driver->provider,
5156                            r->provider);
5157
5158         return WERR_OK;
5159 }
5160
5161 /********************************************************************
5162  * fill a spoolss_DriverInfo8 struct
5163  ********************************************************************/
5164
5165 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5166                                         struct spoolss_DriverInfo8 *r,
5167                                         const struct spoolss_DriverInfo8 *driver,
5168                                         const char *servername)
5169 {
5170         const char *cservername = canon_servername(servername);
5171         WERROR result;
5172
5173         r->version              = driver->version;
5174
5175         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5176         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5177         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5178         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5179
5180         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181                                driver->architecture,
5182                                driver->version,
5183                                driver->driver_path,
5184                                r->driver_path);
5185
5186         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187                                driver->architecture,
5188                                driver->version,
5189                                driver->data_file,
5190                                r->data_file);
5191
5192         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5193                                driver->architecture,
5194                                driver->version,
5195                                driver->config_file,
5196                                r->config_file);
5197
5198         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5199                                driver->architecture,
5200                                driver->version,
5201                                driver->help_file,
5202                                r->help_file);
5203
5204         FILL_DRIVER_STRING(mem_ctx,
5205                            driver->monitor_name,
5206                            r->monitor_name);
5207
5208         FILL_DRIVER_STRING(mem_ctx,
5209                            driver->default_datatype,
5210                            r->default_datatype);
5211
5212         result = string_array_from_driver_info(mem_ctx,
5213                                                driver->dependent_files,
5214                                                &r->dependent_files,
5215                                                cservername,
5216                                                driver->architecture,
5217                                                driver->version);
5218         if (!W_ERROR_IS_OK(result)) {
5219                 return result;
5220         }
5221
5222         result = string_array_from_driver_info(mem_ctx,
5223                                                driver->previous_names,
5224                                                &r->previous_names,
5225                                                NULL, NULL, 0);
5226         if (!W_ERROR_IS_OK(result)) {
5227                 return result;
5228         }
5229
5230         r->driver_date          = driver->driver_date;
5231         r->driver_version       = driver->driver_version;
5232
5233         FILL_DRIVER_STRING(mem_ctx,
5234                            driver->manufacturer_name,
5235                            r->manufacturer_name);
5236         FILL_DRIVER_STRING(mem_ctx,
5237                            driver->manufacturer_url,
5238                            r->manufacturer_url);
5239         FILL_DRIVER_STRING(mem_ctx,
5240                            driver->hardware_id,
5241                            r->hardware_id);
5242         FILL_DRIVER_STRING(mem_ctx,
5243                            driver->provider,
5244                            r->provider);
5245
5246         FILL_DRIVER_STRING(mem_ctx,
5247                            driver->print_processor,
5248                            r->print_processor);
5249         FILL_DRIVER_STRING(mem_ctx,
5250                            driver->vendor_setup,
5251                            r->vendor_setup);
5252
5253         result = string_array_from_driver_info(mem_ctx,
5254                                                driver->color_profiles,
5255                                                &r->color_profiles,
5256                                                NULL, NULL, 0);
5257         if (!W_ERROR_IS_OK(result)) {
5258                 return result;
5259         }
5260
5261         FILL_DRIVER_STRING(mem_ctx,
5262                            driver->inf_path,
5263                            r->inf_path);
5264
5265         r->printer_driver_attributes    = driver->printer_driver_attributes;
5266
5267         result = string_array_from_driver_info(mem_ctx,
5268                                                driver->core_driver_dependencies,
5269                                                &r->core_driver_dependencies,
5270                                                NULL, NULL, 0);
5271         if (!W_ERROR_IS_OK(result)) {
5272                 return result;
5273         }
5274
5275         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5276         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5277
5278         return WERR_OK;
5279 }
5280
5281 #if 0 /* disabled until marshalling issues are resolved - gd */
5282 /********************************************************************
5283  ********************************************************************/
5284
5285 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5286                                           struct spoolss_DriverFileInfo *r,
5287                                           const char *cservername,
5288                                           const char *file_name,
5289                                           enum spoolss_DriverFileType file_type,
5290                                           uint32_t file_version)
5291 {
5292         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5293                                           cservername, file_name);
5294         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5295         r->file_type    = file_type;
5296         r->file_version = file_version;
5297
5298         return WERR_OK;
5299 }
5300
5301 /********************************************************************
5302  ********************************************************************/
5303
5304 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5305                                                  const struct spoolss_DriverInfo8 *driver,
5306                                                  const char *cservername,
5307                                                  struct spoolss_DriverFileInfo **info_p,
5308                                                  uint32_t *count_p)
5309 {
5310         struct spoolss_DriverFileInfo *info = NULL;
5311         uint32_t count = 0;
5312         WERROR result;
5313         uint32_t i;
5314
5315         *info_p = NULL;
5316         *count_p = 0;
5317
5318         if (strlen(driver->driver_path)) {
5319                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5320                                             struct spoolss_DriverFileInfo,
5321                                             count + 1);
5322                 W_ERROR_HAVE_NO_MEMORY(info);
5323                 result = fill_spoolss_DriverFileInfo(info,
5324                                                      &info[count],
5325                                                      cservername,
5326                                                      driver->driver_path,
5327                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5328                                                      0);
5329                 W_ERROR_NOT_OK_RETURN(result);
5330                 count++;
5331         }
5332
5333         if (strlen(driver->config_file)) {
5334                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5335                                             struct spoolss_DriverFileInfo,
5336                                             count + 1);
5337                 W_ERROR_HAVE_NO_MEMORY(info);
5338                 result = fill_spoolss_DriverFileInfo(info,
5339                                                      &info[count],
5340                                                      cservername,
5341                                                      driver->config_file,
5342                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5343                                                      0);
5344                 W_ERROR_NOT_OK_RETURN(result);
5345                 count++;
5346         }
5347
5348         if (strlen(driver->data_file)) {
5349                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5350                                             struct spoolss_DriverFileInfo,
5351                                             count + 1);
5352                 W_ERROR_HAVE_NO_MEMORY(info);
5353                 result = fill_spoolss_DriverFileInfo(info,
5354                                                      &info[count],
5355                                                      cservername,
5356                                                      driver->data_file,
5357                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5358                                                      0);
5359                 W_ERROR_NOT_OK_RETURN(result);
5360                 count++;
5361         }
5362
5363         if (strlen(driver->help_file)) {
5364                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5365                                             struct spoolss_DriverFileInfo,
5366                                             count + 1);
5367                 W_ERROR_HAVE_NO_MEMORY(info);
5368                 result = fill_spoolss_DriverFileInfo(info,
5369                                                      &info[count],
5370                                                      cservername,
5371                                                      driver->help_file,
5372                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5373                                                      0);
5374                 W_ERROR_NOT_OK_RETURN(result);
5375                 count++;
5376         }
5377
5378         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5379                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5380                                             struct spoolss_DriverFileInfo,
5381                                             count + 1);
5382                 W_ERROR_HAVE_NO_MEMORY(info);
5383                 result = fill_spoolss_DriverFileInfo(info,
5384                                                      &info[count],
5385                                                      cservername,
5386                                                      driver->dependent_files[i],
5387                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5388                                                      0);
5389                 W_ERROR_NOT_OK_RETURN(result);
5390                 count++;
5391         }
5392
5393         *info_p = info;
5394         *count_p = count;
5395
5396         return WERR_OK;
5397 }
5398
5399 /********************************************************************
5400  * fill a spoolss_DriverInfo101 struct
5401  ********************************************************************/
5402
5403 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5404                                           struct spoolss_DriverInfo101 *r,
5405                                           const struct spoolss_DriverInfo8 *driver,
5406                                           const char *servername)
5407 {
5408         const char *cservername = canon_servername(servername);
5409         WERROR result;
5410
5411         r->version              = driver->version;
5412
5413         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5414         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5415         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5416         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5417
5418         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5419                                                     cservername,
5420                                                     &r->file_info,
5421                                                     &r->file_count);
5422         if (!W_ERROR_IS_OK(result)) {
5423                 return result;
5424         }
5425
5426         FILL_DRIVER_STRING(mem_ctx,
5427                            driver->monitor_name,
5428                            r->monitor_name);
5429
5430         FILL_DRIVER_STRING(mem_ctx,
5431                            driver->default_datatype,
5432                            r->default_datatype);
5433
5434         result = string_array_from_driver_info(mem_ctx,
5435                                                driver->previous_names,
5436                                                &r->previous_names,
5437                                                NULL, NULL, 0);
5438         if (!W_ERROR_IS_OK(result)) {
5439                 return result;
5440         }
5441
5442         r->driver_date          = driver->driver_date;
5443         r->driver_version       = driver->driver_version;
5444
5445         FILL_DRIVER_STRING(mem_ctx,
5446                            driver->manufacturer_name,
5447                            r->manufacturer_name);
5448         FILL_DRIVER_STRING(mem_ctx,
5449                            driver->manufacturer_url,
5450                            r->manufacturer_url);
5451         FILL_DRIVER_STRING(mem_ctx,
5452                            driver->hardware_id,
5453                            r->hardware_id);
5454         FILL_DRIVER_STRING(mem_ctx,
5455                            driver->provider,
5456                            r->provider);
5457
5458         return WERR_OK;
5459 }
5460 #endif
5461 /********************************************************************
5462  ********************************************************************/
5463
5464 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5465                                                   const struct auth_serversupplied_info *session_info,
5466                                                   struct messaging_context *msg_ctx,
5467                                                   uint32_t level,
5468                                                   union spoolss_DriverInfo *r,
5469                                                   int snum,
5470                                                   const char *servername,
5471                                                   const char *architecture,
5472                                                   uint32_t version)
5473 {
5474         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5475         struct spoolss_DriverInfo8 *driver;
5476         WERROR result;
5477
5478         if (level == 101) {
5479                 return WERR_UNKNOWN_LEVEL;
5480         }
5481
5482         result = winreg_get_printer(mem_ctx,
5483                                     session_info,
5484                                     msg_ctx,
5485                                     lp_const_servicename(snum),
5486                                     &pinfo2);
5487
5488         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5489                 win_errstr(result)));
5490
5491         if (!W_ERROR_IS_OK(result)) {
5492                 return WERR_INVALID_PRINTER_NAME;
5493         }
5494
5495         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5496                                    architecture,
5497                                    pinfo2->drivername, version, &driver);
5498
5499         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5500                 win_errstr(result)));
5501
5502         if (!W_ERROR_IS_OK(result)) {
5503                 /*
5504                  * Is this a W2k client ?
5505                  */
5506
5507                 if (version < 3) {
5508                         talloc_free(pinfo2);
5509                         return WERR_UNKNOWN_PRINTER_DRIVER;
5510                 }
5511
5512                 /* Yes - try again with a WinNT driver. */
5513                 version = 2;
5514                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5515                                            architecture,
5516                                            pinfo2->drivername,
5517                                            version, &driver);
5518                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5519                         win_errstr(result)));
5520                 if (!W_ERROR_IS_OK(result)) {
5521                         talloc_free(pinfo2);
5522                         return WERR_UNKNOWN_PRINTER_DRIVER;
5523                 }
5524         }
5525
5526         switch (level) {
5527         case 1:
5528                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5529                 break;
5530         case 2:
5531                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5532                 break;
5533         case 3:
5534                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5535                 break;
5536         case 4:
5537                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5538                 break;
5539         case 5:
5540                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5541                 break;
5542         case 6:
5543                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5544                 break;
5545         case 8:
5546                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5547                 break;
5548 #if 0 /* disabled until marshalling issues are resolved - gd */
5549         case 101:
5550                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5551                 break;
5552 #endif
5553         default:
5554                 result = WERR_UNKNOWN_LEVEL;
5555                 break;
5556         }
5557
5558         talloc_free(pinfo2);
5559         talloc_free(driver);
5560
5561         return result;
5562 }
5563
5564 /****************************************************************
5565  _spoolss_GetPrinterDriver2
5566 ****************************************************************/
5567
5568 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5569                                   struct spoolss_GetPrinterDriver2 *r)
5570 {
5571         struct printer_handle *printer;
5572         WERROR result;
5573
5574         int snum;
5575
5576         /* that's an [in out] buffer */
5577
5578         if (!r->in.buffer && (r->in.offered != 0)) {
5579                 return WERR_INVALID_PARAM;
5580         }
5581
5582         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5583
5584         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5585                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5586                 return WERR_INVALID_PRINTER_NAME;
5587         }
5588
5589         *r->out.needed = 0;
5590         *r->out.server_major_version = 0;
5591         *r->out.server_minor_version = 0;
5592
5593         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5594                 return WERR_BADFID;
5595         }
5596
5597         result = construct_printer_driver_info_level(p->mem_ctx,
5598                                                      get_session_info_system(),
5599                                                      p->msg_ctx,
5600                                                      r->in.level, r->out.info,
5601                                                      snum, printer->servername,
5602                                                      r->in.architecture,
5603                                                      r->in.client_major_version);
5604         if (!W_ERROR_IS_OK(result)) {
5605                 TALLOC_FREE(r->out.info);
5606                 return result;
5607         }
5608
5609         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5610                                                r->out.info, r->in.level);
5611         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5612
5613         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5614 }
5615
5616
5617 /****************************************************************
5618  _spoolss_StartPagePrinter
5619 ****************************************************************/
5620
5621 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5622                                  struct spoolss_StartPagePrinter *r)
5623 {
5624         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5625
5626         if (!Printer) {
5627                 DEBUG(3,("_spoolss_StartPagePrinter: "
5628                         "Error in startpageprinter printer handle\n"));
5629                 return WERR_BADFID;
5630         }
5631
5632         Printer->page_started = true;
5633         return WERR_OK;
5634 }
5635
5636 /****************************************************************
5637  _spoolss_EndPagePrinter
5638 ****************************************************************/
5639
5640 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5641                                struct spoolss_EndPagePrinter *r)
5642 {
5643         int snum;
5644
5645         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5646
5647         if (!Printer) {
5648                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5649                         OUR_HANDLE(r->in.handle)));
5650                 return WERR_BADFID;
5651         }
5652
5653         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5654                 return WERR_BADFID;
5655
5656         Printer->page_started = false;
5657         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5658
5659         return WERR_OK;
5660 }
5661
5662 /****************************************************************
5663  _spoolss_StartDocPrinter
5664 ****************************************************************/
5665
5666 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5667                                 struct spoolss_StartDocPrinter *r)
5668 {
5669         struct spoolss_DocumentInfo1 *info_1;
5670         int snum;
5671         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5672         WERROR werr;
5673
5674         if (!Printer) {
5675                 DEBUG(2,("_spoolss_StartDocPrinter: "
5676                         "Invalid handle (%s:%u:%u)\n",
5677                         OUR_HANDLE(r->in.handle)));
5678                 return WERR_BADFID;
5679         }
5680
5681         if (Printer->jobid) {
5682                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5683                           "StartDocPrinter called twice! "
5684                           "(existing jobid = %d)\n", Printer->jobid));
5685                 return WERR_INVALID_HANDLE;
5686         }
5687
5688         if (r->in.level != 1) {
5689                 return WERR_UNKNOWN_LEVEL;
5690         }
5691
5692         info_1 = r->in.info.info1;
5693
5694         /*
5695          * a nice thing with NT is it doesn't listen to what you tell it.
5696          * when asked to send _only_ RAW datas, it tries to send datas
5697          * in EMF format.
5698          *
5699          * So I add checks like in NT Server ...
5700          */
5701
5702         if (info_1->datatype) {
5703                 if (strcmp(info_1->datatype, "RAW") != 0) {
5704                         *r->out.job_id = 0;
5705                         return WERR_INVALID_DATATYPE;
5706                 }
5707         }
5708
5709         /* get the share number of the printer */
5710         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5711                 return WERR_BADFID;
5712         }
5713
5714         werr = print_job_start(p->session_info,
5715                                p->msg_ctx,
5716                                p->client_id->name,
5717                                snum,
5718                                info_1->document_name,
5719                                info_1->output_file,
5720                                Printer->devmode,
5721                                &Printer->jobid);
5722
5723         /* An error occured in print_job_start() so return an appropriate
5724            NT error code. */
5725
5726         if (!W_ERROR_IS_OK(werr)) {
5727                 return werr;
5728         }
5729
5730         Printer->document_started = true;
5731         *r->out.job_id = Printer->jobid;
5732
5733         return WERR_OK;
5734 }
5735
5736 /****************************************************************
5737  _spoolss_EndDocPrinter
5738 ****************************************************************/
5739
5740 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5741                               struct spoolss_EndDocPrinter *r)
5742 {
5743         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5744         NTSTATUS status;
5745         int snum;
5746
5747         if (!Printer) {
5748                 DEBUG(2,("_spoolss_EndDocPrinter: 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
5757         Printer->document_started = false;
5758         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5759         if (!NT_STATUS_IS_OK(status)) {
5760                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5761                           "print_job_end failed [%s]\n",
5762                           nt_errstr(status)));
5763         }
5764
5765         Printer->jobid = 0;
5766         return ntstatus_to_werror(status);
5767 }
5768
5769 /****************************************************************
5770  _spoolss_WritePrinter
5771 ****************************************************************/
5772
5773 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5774                              struct spoolss_WritePrinter *r)
5775 {
5776         ssize_t buffer_written;
5777         int snum;
5778         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5779
5780         if (!Printer) {
5781                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5782                         OUR_HANDLE(r->in.handle)));
5783                 *r->out.num_written = r->in._data_size;
5784                 return WERR_BADFID;
5785         }
5786
5787         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5788                 return WERR_BADFID;
5789
5790         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5791         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5792                                                    snum, Printer->jobid,
5793                                                    (const char *)r->in.data.data,
5794                                                    (size_t)r->in._data_size);
5795         if (buffer_written == (ssize_t)-1) {
5796                 *r->out.num_written = 0;
5797                 if (errno == ENOSPC)
5798                         return WERR_NO_SPOOL_SPACE;
5799                 else
5800                         return WERR_ACCESS_DENIED;
5801         }
5802
5803         *r->out.num_written = r->in._data_size;
5804
5805         return WERR_OK;
5806 }
5807
5808 /********************************************************************
5809  * api_spoolss_getprinter
5810  * called from the spoolss dispatcher
5811  *
5812  ********************************************************************/
5813
5814 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5815                               struct pipes_struct *p)
5816 {
5817         const struct auth_serversupplied_info *session_info = p->session_info;
5818         int snum;
5819         WERROR errcode = WERR_BADFUNC;
5820         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5821
5822         if (!Printer) {
5823                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5824                         OUR_HANDLE(handle)));
5825                 return WERR_BADFID;
5826         }
5827
5828         if (!get_printer_snum(p, handle, &snum, NULL))
5829                 return WERR_BADFID;
5830
5831         switch (command) {
5832         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5833                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5834                 break;
5835         case SPOOLSS_PRINTER_CONTROL_RESUME:
5836         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5837                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5838                 break;
5839         case SPOOLSS_PRINTER_CONTROL_PURGE:
5840                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5841                 break;
5842         default:
5843                 return WERR_UNKNOWN_LEVEL;
5844         }
5845
5846         return errcode;
5847 }
5848
5849
5850 /****************************************************************
5851  _spoolss_AbortPrinter
5852  * From MSDN: "Deletes printer's spool file if printer is configured
5853  * for spooling"
5854 ****************************************************************/
5855
5856 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5857                              struct spoolss_AbortPrinter *r)
5858 {
5859         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5860         int             snum;
5861         WERROR          errcode = WERR_OK;
5862
5863         if (!Printer) {
5864                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5865                         OUR_HANDLE(r->in.handle)));
5866                 return WERR_BADFID;
5867         }
5868
5869         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5870                 return WERR_BADFID;
5871
5872         if (!Printer->document_started) {
5873                 return WERR_SPL_NO_STARTDOC;
5874         }
5875
5876         errcode = print_job_delete(p->session_info,
5877                                    p->msg_ctx,
5878                                    snum,
5879                                    Printer->jobid);
5880
5881         return errcode;
5882 }
5883
5884 /********************************************************************
5885  * called by spoolss_api_setprinter
5886  * when updating a printer description
5887  ********************************************************************/
5888
5889 static WERROR update_printer_sec(struct policy_handle *handle,
5890                                  struct pipes_struct *p,
5891                                  struct sec_desc_buf *secdesc_ctr)
5892 {
5893         struct spoolss_security_descriptor *new_secdesc = NULL;
5894         struct spoolss_security_descriptor *old_secdesc = NULL;
5895         const char *printer;
5896         WERROR result;
5897         int snum;
5898
5899         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5900
5901         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5902                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5903                          OUR_HANDLE(handle)));
5904
5905                 result = WERR_BADFID;
5906                 goto done;
5907         }
5908
5909         if (secdesc_ctr == NULL) {
5910                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5911                 result = WERR_INVALID_PARAM;
5912                 goto done;
5913         }
5914         printer = lp_const_servicename(snum);
5915
5916         /* Check the user has permissions to change the security
5917            descriptor.  By experimentation with two NT machines, the user
5918            requires Full Access to the printer to change security
5919            information. */
5920
5921         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5922                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5923                 result = WERR_ACCESS_DENIED;
5924                 goto done;
5925         }
5926
5927         /* NT seems to like setting the security descriptor even though
5928            nothing may have actually changed. */
5929         result = winreg_get_printer_secdesc(p->mem_ctx,
5930                                             get_session_info_system(),
5931                                             p->msg_ctx,
5932                                             printer,
5933                                             &old_secdesc);
5934         if (!W_ERROR_IS_OK(result)) {
5935                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5936                 result = WERR_BADFID;
5937                 goto done;
5938         }
5939
5940         if (DEBUGLEVEL >= 10) {
5941                 struct security_acl *the_acl;
5942                 int i;
5943
5944                 the_acl = old_secdesc->dacl;
5945                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5946                            printer, the_acl->num_aces));
5947
5948                 for (i = 0; i < the_acl->num_aces; i++) {
5949                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5950                                            &the_acl->aces[i].trustee),
5951                                   the_acl->aces[i].access_mask));
5952                 }
5953
5954                 the_acl = secdesc_ctr->sd->dacl;
5955
5956                 if (the_acl) {
5957                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5958                                    printer, the_acl->num_aces));
5959
5960                         for (i = 0; i < the_acl->num_aces; i++) {
5961                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5962                                                    &the_acl->aces[i].trustee),
5963                                            the_acl->aces[i].access_mask));
5964                         }
5965                 } else {
5966                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5967                 }
5968         }
5969
5970         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5971         if (new_secdesc == NULL) {
5972                 result = WERR_NOMEM;
5973                 goto done;
5974         }
5975
5976         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5977                 result = WERR_OK;
5978                 goto done;
5979         }
5980
5981         result = winreg_set_printer_secdesc(p->mem_ctx,
5982                                             get_session_info_system(),
5983                                             p->msg_ctx,
5984                                             printer,
5985                                             new_secdesc);
5986
5987  done:
5988         return result;
5989 }
5990
5991 /********************************************************************
5992  Canonicalize printer info from a client
5993  ********************************************************************/
5994
5995 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5996                              struct spoolss_SetPrinterInfo2 *info2,
5997                              int snum)
5998 {
5999         fstring printername;
6000         const char *p;
6001
6002         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6003                 "portname=%s drivername=%s comment=%s location=%s\n",
6004                 info2->servername, info2->printername, info2->sharename,
6005                 info2->portname, info2->drivername, info2->comment,
6006                 info2->location));
6007
6008         /* we force some elements to "correct" values */
6009         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6010         if (info2->servername == NULL) {
6011                 return false;
6012         }
6013         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6014         if (info2->sharename == NULL) {
6015                 return false;
6016         }
6017
6018         /* check to see if we allow printername != sharename */
6019         if (lp_force_printername(snum)) {
6020                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6021                                         global_myname(), info2->sharename);
6022         } else {
6023                 /* make sure printername is in \\server\printername format */
6024                 fstrcpy(printername, info2->printername);
6025                 p = printername;
6026                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6027                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6028                                 p++;
6029                 }
6030
6031                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6032                                         global_myname(), p);
6033         }
6034         if (info2->printername == NULL) {
6035                 return false;
6036         }
6037
6038         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6039         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6040
6041         return true;
6042 }
6043
6044 /****************************************************************************
6045 ****************************************************************************/
6046
6047 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6048 {
6049         char *cmd = lp_addport_cmd();
6050         char *command = NULL;
6051         int ret;
6052         bool is_print_op = false;
6053
6054         if ( !*cmd ) {
6055                 return WERR_ACCESS_DENIED;
6056         }
6057
6058         command = talloc_asprintf(ctx,
6059                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6060         if (!command) {
6061                 return WERR_NOMEM;
6062         }
6063
6064         if ( token )
6065                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6066
6067         DEBUG(10,("Running [%s]\n", command));
6068
6069         /********* BEGIN SePrintOperatorPrivilege **********/
6070
6071         if ( is_print_op )
6072                 become_root();
6073
6074         ret = smbrun(command, NULL);
6075
6076         if ( is_print_op )
6077                 unbecome_root();
6078
6079         /********* END SePrintOperatorPrivilege **********/
6080
6081         DEBUGADD(10,("returned [%d]\n", ret));
6082
6083         TALLOC_FREE(command);
6084
6085         if ( ret != 0 ) {
6086                 return WERR_ACCESS_DENIED;
6087         }
6088
6089         return WERR_OK;
6090 }
6091
6092 /****************************************************************************
6093 ****************************************************************************/
6094
6095 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6096                              struct spoolss_SetPrinterInfo2 *info2,
6097                              const char *remote_machine,
6098                              struct messaging_context *msg_ctx)
6099 {
6100         char *cmd = lp_addprinter_cmd();
6101         char **qlines;
6102         char *command = NULL;
6103         int numlines;
6104         int ret;
6105         int fd;
6106         bool is_print_op = false;
6107
6108         if (!remote_machine) {
6109                 return false;
6110         }
6111
6112         command = talloc_asprintf(ctx,
6113                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6114                         cmd, info2->printername, info2->sharename,
6115                         info2->portname, info2->drivername,
6116                         info2->location, info2->comment, remote_machine);
6117         if (!command) {
6118                 return false;
6119         }
6120
6121         if ( token )
6122                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6123
6124         DEBUG(10,("Running [%s]\n", command));
6125
6126         /********* BEGIN SePrintOperatorPrivilege **********/
6127
6128         if ( is_print_op )
6129                 become_root();
6130
6131         if ( (ret = smbrun(command, &fd)) == 0 ) {
6132                 /* Tell everyone we updated smb.conf. */
6133                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6134         }
6135
6136         if ( is_print_op )
6137                 unbecome_root();
6138
6139         /********* END SePrintOperatorPrivilege **********/
6140
6141         DEBUGADD(10,("returned [%d]\n", ret));
6142
6143         TALLOC_FREE(command);
6144
6145         if ( ret != 0 ) {
6146                 if (fd != -1)
6147                         close(fd);
6148                 return false;
6149         }
6150
6151         /* reload our services immediately */
6152         become_root();
6153         reload_services(msg_ctx, -1, false);
6154         unbecome_root();
6155
6156         numlines = 0;
6157         /* Get lines and convert them back to dos-codepage */
6158         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6159         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6160         close(fd);
6161
6162         /* Set the portname to what the script says the portname should be. */
6163         /* but don't require anything to be return from the script exit a good error code */
6164
6165         if (numlines) {
6166                 /* Set the portname to what the script says the portname should be. */
6167                 info2->portname = talloc_strdup(ctx, qlines[0]);
6168                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6169         }
6170
6171         TALLOC_FREE(qlines);
6172         return true;
6173 }
6174
6175 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6176                                const struct auth_serversupplied_info *session_info,
6177                                struct messaging_context *msg_ctx,
6178                                int snum,
6179                                struct spoolss_SetPrinterInfo2 *printer,
6180                                struct spoolss_PrinterInfo2 *old_printer)
6181 {
6182         bool force_update = (old_printer == NULL);
6183         const char *dnsdomname;
6184         const char *longname;
6185         const char *uncname;
6186         const char *spooling;
6187         DATA_BLOB buffer;
6188         WERROR result = WERR_OK;
6189
6190         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6191                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6192                 winreg_set_printer_dataex(mem_ctx,
6193                                           session_info,
6194                                           msg_ctx,
6195                                           printer->sharename,
6196                                           SPOOL_DSSPOOLER_KEY,
6197                                           SPOOL_REG_DRIVERNAME,
6198                                           REG_SZ,
6199                                           buffer.data,
6200                                           buffer.length);
6201
6202                 if (!force_update) {
6203                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6204                                 printer->drivername));
6205
6206                         notify_printer_driver(server_event_context(), msg_ctx,
6207                                               snum, printer->drivername ?
6208                                               printer->drivername : "");
6209                 }
6210         }
6211
6212         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6213                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6214                 winreg_set_printer_dataex(mem_ctx,
6215                                           session_info,
6216                                           msg_ctx,
6217                                           printer->sharename,
6218                                           SPOOL_DSSPOOLER_KEY,
6219                                           SPOOL_REG_DESCRIPTION,
6220                                           REG_SZ,
6221                                           buffer.data,
6222                                           buffer.length);
6223
6224                 if (!force_update) {
6225                         notify_printer_comment(server_event_context(), msg_ctx,
6226                                                snum, printer->comment ?
6227                                                printer->comment : "");
6228                 }
6229         }
6230
6231         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6232                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6233                 winreg_set_printer_dataex(mem_ctx,
6234                                           session_info,
6235                                           msg_ctx,
6236                                           printer->sharename,
6237                                           SPOOL_DSSPOOLER_KEY,
6238                                           SPOOL_REG_PRINTSHARENAME,
6239                                           REG_SZ,
6240                                           buffer.data,
6241                                           buffer.length);
6242
6243                 if (!force_update) {
6244                         notify_printer_sharename(server_event_context(),
6245                                                  msg_ctx,
6246                                                  snum, printer->sharename ?
6247                                                  printer->sharename : "");
6248                 }
6249         }
6250
6251         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6252                 const char *p;
6253
6254                 p = strrchr(printer->printername, '\\' );
6255                 if (p != NULL) {
6256                         p++;
6257                 } else {
6258                         p = printer->printername;
6259                 }
6260
6261                 push_reg_sz(mem_ctx, &buffer, p);
6262                 winreg_set_printer_dataex(mem_ctx,
6263                                           session_info,
6264                                           msg_ctx,
6265                                           printer->sharename,
6266                                           SPOOL_DSSPOOLER_KEY,
6267                                           SPOOL_REG_PRINTERNAME,
6268                                           REG_SZ,
6269                                           buffer.data,
6270                                           buffer.length);
6271
6272                 if (!force_update) {
6273                         notify_printer_printername(server_event_context(),
6274                                                    msg_ctx, snum, p ? p : "");
6275                 }
6276         }
6277
6278         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6279                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6280                 winreg_set_printer_dataex(mem_ctx,
6281                                           session_info,
6282                                           msg_ctx,
6283                                           printer->sharename,
6284                                           SPOOL_DSSPOOLER_KEY,
6285                                           SPOOL_REG_PORTNAME,
6286                                           REG_SZ,
6287                                           buffer.data,
6288                                           buffer.length);
6289
6290                 if (!force_update) {
6291                         notify_printer_port(server_event_context(),
6292                                             msg_ctx, snum, printer->portname ?
6293                                             printer->portname : "");
6294                 }
6295         }
6296
6297         if (force_update || !strequal(printer->location, old_printer->location)) {
6298                 push_reg_sz(mem_ctx, &buffer, printer->location);
6299                 winreg_set_printer_dataex(mem_ctx,
6300                                           session_info,
6301                                           msg_ctx,
6302                                           printer->sharename,
6303                                           SPOOL_DSSPOOLER_KEY,
6304                                           SPOOL_REG_LOCATION,
6305                                           REG_SZ,
6306                                           buffer.data,
6307                                           buffer.length);
6308
6309                 if (!force_update) {
6310                         notify_printer_location(server_event_context(),
6311                                                 msg_ctx, snum,
6312                                                 printer->location ?
6313                                                 printer->location : "");
6314                 }
6315         }
6316
6317         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6318                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6319                 winreg_set_printer_dataex(mem_ctx,
6320                                           session_info,
6321                                           msg_ctx,
6322                                           printer->sharename,
6323                                           SPOOL_DSSPOOLER_KEY,
6324                                           SPOOL_REG_PRINTSEPARATORFILE,
6325                                           REG_SZ,
6326                                           buffer.data,
6327                                           buffer.length);
6328
6329                 if (!force_update) {
6330                         notify_printer_sepfile(server_event_context(),
6331                                                msg_ctx, snum,
6332                                                printer->sepfile ?
6333                                                printer->sepfile : "");
6334                 }
6335         }
6336
6337         if (force_update || printer->starttime != old_printer->starttime) {
6338                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6339                 SIVAL(buffer.data, 0, printer->starttime);
6340                 winreg_set_printer_dataex(mem_ctx,
6341                                           session_info,
6342                                           msg_ctx,
6343                                           printer->sharename,
6344                                           SPOOL_DSSPOOLER_KEY,
6345                                           SPOOL_REG_PRINTSTARTTIME,
6346                                           REG_DWORD,
6347                                           buffer.data,
6348                                           buffer.length);
6349         }
6350
6351         if (force_update || printer->untiltime != old_printer->untiltime) {
6352                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6353                 SIVAL(buffer.data, 0, printer->untiltime);
6354                 winreg_set_printer_dataex(mem_ctx,
6355                                           session_info,
6356                                           msg_ctx,
6357                                           printer->sharename,
6358                                           SPOOL_DSSPOOLER_KEY,
6359                                           SPOOL_REG_PRINTENDTIME,
6360                                           REG_DWORD,
6361                                           buffer.data,
6362                                           buffer.length);
6363         }
6364
6365         if (force_update || printer->priority != old_printer->priority) {
6366                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6367                 SIVAL(buffer.data, 0, printer->priority);
6368                 winreg_set_printer_dataex(mem_ctx,
6369                                           session_info,
6370                                           msg_ctx,
6371                                           printer->sharename,
6372                                           SPOOL_DSSPOOLER_KEY,
6373                                           SPOOL_REG_PRIORITY,
6374                                           REG_DWORD,
6375                                           buffer.data,
6376                                           buffer.length);
6377         }
6378
6379         if (force_update || printer->attributes != old_printer->attributes) {
6380                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6381                 SIVAL(buffer.data, 0, (printer->attributes &
6382                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6383                 winreg_set_printer_dataex(mem_ctx,
6384                                           session_info,
6385                                           msg_ctx,
6386                                           printer->sharename,
6387                                           SPOOL_DSSPOOLER_KEY,
6388                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6389                                           REG_DWORD,
6390                                           buffer.data,
6391                                           buffer.length);
6392
6393                 switch (printer->attributes & 0x3) {
6394                         case 0:
6395                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6396                                 break;
6397                         case 1:
6398                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6399                                 break;
6400                         case 2:
6401                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6402                                 break;
6403                         default:
6404                                 spooling = "unknown";
6405                 }
6406                 push_reg_sz(mem_ctx, &buffer, spooling);
6407                 winreg_set_printer_dataex(mem_ctx,
6408                                           session_info,
6409                                           msg_ctx,
6410                                           printer->sharename,
6411                                           SPOOL_DSSPOOLER_KEY,
6412                                           SPOOL_REG_PRINTSPOOLING,
6413                                           REG_SZ,
6414                                           buffer.data,
6415                                           buffer.length);
6416         }
6417
6418         push_reg_sz(mem_ctx, &buffer, global_myname());
6419         winreg_set_printer_dataex(mem_ctx,
6420                                   session_info,
6421                                   msg_ctx,
6422                                   printer->sharename,
6423                                   SPOOL_DSSPOOLER_KEY,
6424                                   SPOOL_REG_SHORTSERVERNAME,
6425                                   REG_SZ,
6426                                   buffer.data,
6427                                   buffer.length);
6428
6429         dnsdomname = get_mydnsfullname();
6430         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6431                 longname = talloc_strdup(mem_ctx, dnsdomname);
6432         } else {
6433                 longname = talloc_strdup(mem_ctx, global_myname());
6434         }
6435         if (longname == NULL) {
6436                 result = WERR_NOMEM;
6437                 goto done;
6438         }
6439
6440         push_reg_sz(mem_ctx, &buffer, longname);
6441         winreg_set_printer_dataex(mem_ctx,
6442                                   session_info,
6443                                   msg_ctx,
6444                                   printer->sharename,
6445                                   SPOOL_DSSPOOLER_KEY,
6446                                   SPOOL_REG_SERVERNAME,
6447                                   REG_SZ,
6448                                   buffer.data,
6449                                   buffer.length);
6450
6451         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6452                                   global_myname(), printer->sharename);
6453         push_reg_sz(mem_ctx, &buffer, uncname);
6454         winreg_set_printer_dataex(mem_ctx,
6455                                   session_info,
6456                                   msg_ctx,
6457                                   printer->sharename,
6458                                   SPOOL_DSSPOOLER_KEY,
6459                                   SPOOL_REG_UNCNAME,
6460                                   REG_SZ,
6461                                   buffer.data,
6462                                   buffer.length);
6463
6464 done:
6465         return result;
6466 }
6467
6468 /********************************************************************
6469  * Called by spoolss_api_setprinter
6470  * when updating a printer description.
6471  ********************************************************************/
6472
6473 static WERROR update_printer(struct pipes_struct *p,
6474                              struct policy_handle *handle,
6475                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6476                              struct spoolss_DeviceMode *devmode)
6477 {
6478         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6479         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6480         struct spoolss_PrinterInfo2 *old_printer;
6481         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6482         int snum;
6483         WERROR result = WERR_OK;
6484         TALLOC_CTX *tmp_ctx;
6485
6486         DEBUG(8,("update_printer\n"));
6487
6488         tmp_ctx = talloc_new(p->mem_ctx);
6489         if (tmp_ctx == NULL) {
6490                 return WERR_NOMEM;
6491         }
6492
6493         if (!Printer) {
6494                 result = WERR_BADFID;
6495                 goto done;
6496         }
6497
6498         if (!get_printer_snum(p, handle, &snum, NULL)) {
6499                 result = WERR_BADFID;
6500                 goto done;
6501         }
6502
6503         result = winreg_get_printer(tmp_ctx,
6504                                     get_session_info_system(),
6505                                     p->msg_ctx,
6506                                     lp_const_servicename(snum),
6507                                     &old_printer);
6508         if (!W_ERROR_IS_OK(result)) {
6509                 result = WERR_BADFID;
6510                 goto done;
6511         }
6512
6513         /* Do sanity check on the requested changes for Samba */
6514         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6515                 result = WERR_INVALID_PARAM;
6516                 goto done;
6517         }
6518
6519         /* FIXME!!! If the driver has changed we really should verify that
6520            it is installed before doing much else   --jerry */
6521
6522         /* Check calling user has permission to update printer description */
6523         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6524                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6525                 result = WERR_ACCESS_DENIED;
6526                 goto done;
6527         }
6528
6529         /* Call addprinter hook */
6530         /* Check changes to see if this is really needed */
6531
6532         if (*lp_addprinter_cmd() &&
6533                         (!strequal(printer->drivername, old_printer->drivername) ||
6534                          !strequal(printer->comment, old_printer->comment) ||
6535                          !strequal(printer->portname, old_printer->portname) ||
6536                          !strequal(printer->location, old_printer->location)) )
6537         {
6538                 /* add_printer_hook() will call reload_services() */
6539                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6540                                       printer, p->client_id->addr,
6541                                       p->msg_ctx)) {
6542                         result = WERR_ACCESS_DENIED;
6543                         goto done;
6544                 }
6545         }
6546
6547         update_dsspooler(tmp_ctx,
6548                          get_session_info_system(),
6549                          p->msg_ctx,
6550                          snum,
6551                          printer,
6552                          old_printer);
6553
6554         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6555
6556         if (devmode == NULL) {
6557                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6558         }
6559         result = winreg_update_printer(tmp_ctx,
6560                                        get_session_info_system(),
6561                                        p->msg_ctx,
6562                                        printer->sharename,
6563                                        printer_mask,
6564                                        printer,
6565                                        devmode,
6566                                        NULL);
6567
6568 done:
6569         talloc_free(tmp_ctx);
6570
6571         return result;
6572 }
6573
6574 /****************************************************************************
6575 ****************************************************************************/
6576 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6577                                            struct policy_handle *handle,
6578                                            struct spoolss_SetPrinterInfo7 *info7)
6579 {
6580 #ifdef HAVE_ADS
6581         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6582         WERROR result;
6583         int snum;
6584         struct printer_handle *Printer;
6585
6586         if ( lp_security() != SEC_ADS ) {
6587                 return WERR_UNKNOWN_LEVEL;
6588         }
6589
6590         Printer = find_printer_index_by_hnd(p, handle);
6591
6592         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6593
6594         if (!Printer)
6595                 return WERR_BADFID;
6596
6597         if (!get_printer_snum(p, handle, &snum, NULL))
6598                 return WERR_BADFID;
6599
6600         result = winreg_get_printer(p->mem_ctx,
6601                                     get_session_info_system(),
6602                                     p->msg_ctx,
6603                                     lp_servicename(snum),
6604                                     &pinfo2);
6605         if (!W_ERROR_IS_OK(result)) {
6606                 return WERR_BADFID;
6607         }
6608
6609         nt_printer_publish(pinfo2,
6610                            get_session_info_system(),
6611                            p->msg_ctx,
6612                            pinfo2,
6613                            info7->action);
6614
6615         TALLOC_FREE(pinfo2);
6616         return WERR_OK;
6617 #else
6618         return WERR_UNKNOWN_LEVEL;
6619 #endif
6620 }
6621
6622 /********************************************************************
6623  ********************************************************************/
6624
6625 static WERROR update_printer_devmode(struct pipes_struct *p,
6626                                      struct policy_handle *handle,
6627                                      struct spoolss_DeviceMode *devmode)
6628 {
6629         int snum;
6630         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6631         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6632
6633         DEBUG(8,("update_printer_devmode\n"));
6634
6635         if (!Printer) {
6636                 return WERR_BADFID;
6637         }
6638
6639         if (!get_printer_snum(p, handle, &snum, NULL)) {
6640                 return WERR_BADFID;
6641         }
6642
6643         /* Check calling user has permission to update printer description */
6644         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6645                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6646                 return WERR_ACCESS_DENIED;
6647         }
6648
6649         return winreg_update_printer(p->mem_ctx,
6650                                      get_session_info_system(),
6651                                      p->msg_ctx,
6652                                      lp_const_servicename(snum),
6653                                      info2_mask,
6654                                      NULL,
6655                                      devmode,
6656                                      NULL);
6657 }
6658
6659
6660 /****************************************************************
6661  _spoolss_SetPrinter
6662 ****************************************************************/
6663
6664 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6665                            struct spoolss_SetPrinter *r)
6666 {
6667         WERROR result;
6668
6669         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6670
6671         if (!Printer) {
6672                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6673                         OUR_HANDLE(r->in.handle)));
6674                 return WERR_BADFID;
6675         }
6676
6677         /* check the level */
6678         switch (r->in.info_ctr->level) {
6679                 case 0:
6680                         return control_printer(r->in.handle, r->in.command, p);
6681                 case 2:
6682                         result = update_printer(p, r->in.handle,
6683                                                 r->in.info_ctr,
6684                                                 r->in.devmode_ctr->devmode);
6685                         if (!W_ERROR_IS_OK(result))
6686                                 return result;
6687                         if (r->in.secdesc_ctr->sd)
6688                                 result = update_printer_sec(r->in.handle, p,
6689                                                             r->in.secdesc_ctr);
6690                         return result;
6691                 case 3:
6692                         return update_printer_sec(r->in.handle, p,
6693                                                   r->in.secdesc_ctr);
6694                 case 7:
6695                         return publish_or_unpublish_printer(p, r->in.handle,
6696                                                             r->in.info_ctr->info.info7);
6697                 case 8:
6698                         return update_printer_devmode(p, r->in.handle,
6699                                                       r->in.devmode_ctr->devmode);
6700                 default:
6701                         return WERR_UNKNOWN_LEVEL;
6702         }
6703 }
6704
6705 /****************************************************************
6706  _spoolss_FindClosePrinterNotify
6707 ****************************************************************/
6708
6709 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6710                                        struct spoolss_FindClosePrinterNotify *r)
6711 {
6712         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6713
6714         if (!Printer) {
6715                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6716                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6717                 return WERR_BADFID;
6718         }
6719
6720         if (Printer->notify.cli_chan != NULL &&
6721             Printer->notify.cli_chan->active_connections > 0) {
6722                 int snum = -1;
6723
6724                 if (Printer->printer_type == SPLHND_PRINTER) {
6725                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6726                                 return WERR_BADFID;
6727                         }
6728                 }
6729
6730                 srv_spoolss_replycloseprinter(snum, Printer);
6731         }
6732
6733         Printer->notify.flags=0;
6734         Printer->notify.options=0;
6735         Printer->notify.localmachine[0]='\0';
6736         Printer->notify.printerlocal=0;
6737         TALLOC_FREE(Printer->notify.option);
6738
6739         return WERR_OK;
6740 }
6741
6742 /****************************************************************
6743  _spoolss_AddJob
6744 ****************************************************************/
6745
6746 WERROR _spoolss_AddJob(struct pipes_struct *p,
6747                        struct spoolss_AddJob *r)
6748 {
6749         if (!r->in.buffer && (r->in.offered != 0)) {
6750                 return WERR_INVALID_PARAM;
6751         }
6752
6753         /* this is what a NT server returns for AddJob. AddJob must fail on
6754          * non-local printers */
6755
6756         if (r->in.level != 1) {
6757                 return WERR_UNKNOWN_LEVEL;
6758         }
6759
6760         return WERR_INVALID_PARAM;
6761 }
6762
6763 /****************************************************************************
6764 fill_job_info1
6765 ****************************************************************************/
6766
6767 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6768                              struct spoolss_JobInfo1 *r,
6769                              const print_queue_struct *queue,
6770                              int position, int snum,
6771                              struct spoolss_PrinterInfo2 *pinfo2)
6772 {
6773         struct tm *t;
6774
6775         t = gmtime(&queue->time);
6776
6777         r->job_id               = queue->job;
6778
6779         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6780         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6781         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6782         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6783         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6784         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6785         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6786         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6787         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6788         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6789         r->text_status          = talloc_strdup(mem_ctx, "");
6790         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6791
6792         r->status               = nt_printj_status(queue->status);
6793         r->priority             = queue->priority;
6794         r->position             = position;
6795         r->total_pages          = queue->page_count;
6796         r->pages_printed        = 0; /* ??? */
6797
6798         init_systemtime(&r->submitted, t);
6799
6800         return WERR_OK;
6801 }
6802
6803 /****************************************************************************
6804 fill_job_info2
6805 ****************************************************************************/
6806
6807 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6808                              struct spoolss_JobInfo2 *r,
6809                              const print_queue_struct *queue,
6810                              int position, int snum,
6811                              struct spoolss_PrinterInfo2 *pinfo2,
6812                              struct spoolss_DeviceMode *devmode)
6813 {
6814         struct tm *t;
6815
6816         t = gmtime(&queue->time);
6817
6818         r->job_id               = queue->job;
6819
6820         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6821         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6822         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6823         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6824         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6825         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6826         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6827         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6828         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6829         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6830         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6831         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6832         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6833         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6834         r->parameters           = talloc_strdup(mem_ctx, "");
6835         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6836         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6837         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6838
6839         r->devmode              = devmode;
6840
6841         r->text_status          = talloc_strdup(mem_ctx, "");
6842         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6843
6844         r->secdesc              = NULL;
6845
6846         r->status               = nt_printj_status(queue->status);
6847         r->priority             = queue->priority;
6848         r->position             = position;
6849         r->start_time           = 0;
6850         r->until_time           = 0;
6851         r->total_pages          = queue->page_count;
6852         r->size                 = queue->size;
6853         init_systemtime(&r->submitted, t);
6854         r->time                 = 0;
6855         r->pages_printed        = 0; /* ??? */
6856
6857         return WERR_OK;
6858 }
6859
6860 /****************************************************************************
6861 fill_job_info3
6862 ****************************************************************************/
6863
6864 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6865                              struct spoolss_JobInfo3 *r,
6866                              const print_queue_struct *queue,
6867                              const print_queue_struct *next_queue,
6868                              int position, int snum,
6869                              struct spoolss_PrinterInfo2 *pinfo2)
6870 {
6871         r->job_id               = queue->job;
6872         r->next_job_id          = 0;
6873         if (next_queue) {
6874                 r->next_job_id  = next_queue->job;
6875         }
6876         r->reserved             = 0;
6877
6878         return WERR_OK;
6879 }
6880
6881 /****************************************************************************
6882  Enumjobs at level 1.
6883 ****************************************************************************/
6884
6885 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6886                               const print_queue_struct *queue,
6887                               uint32_t num_queues, int snum,
6888                               struct spoolss_PrinterInfo2 *pinfo2,
6889                               union spoolss_JobInfo **info_p,
6890                               uint32_t *count)
6891 {
6892         union spoolss_JobInfo *info;
6893         int i;
6894         WERROR result = WERR_OK;
6895
6896         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6897         W_ERROR_HAVE_NO_MEMORY(info);
6898
6899         *count = num_queues;
6900
6901         for (i=0; i<*count; i++) {
6902                 result = fill_job_info1(info,
6903                                         &info[i].info1,
6904                                         &queue[i],
6905                                         i,
6906                                         snum,
6907                                         pinfo2);
6908                 if (!W_ERROR_IS_OK(result)) {
6909                         goto out;
6910                 }
6911         }
6912
6913  out:
6914         if (!W_ERROR_IS_OK(result)) {
6915                 TALLOC_FREE(info);
6916                 *count = 0;
6917                 return result;
6918         }
6919
6920         *info_p = info;
6921
6922         return WERR_OK;
6923 }
6924
6925 /****************************************************************************
6926  Enumjobs at level 2.
6927 ****************************************************************************/
6928
6929 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6930                               const print_queue_struct *queue,
6931                               uint32_t num_queues, int snum,
6932                               struct spoolss_PrinterInfo2 *pinfo2,
6933                               union spoolss_JobInfo **info_p,
6934                               uint32_t *count)
6935 {
6936         union spoolss_JobInfo *info;
6937         int i;
6938         WERROR result = WERR_OK;
6939
6940         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6941         W_ERROR_HAVE_NO_MEMORY(info);
6942
6943         *count = num_queues;
6944
6945         for (i=0; i<*count; i++) {
6946                 struct spoolss_DeviceMode *devmode;
6947
6948                 result = spoolss_create_default_devmode(info,
6949                                                         pinfo2->printername,
6950                                                         &devmode);
6951                 if (!W_ERROR_IS_OK(result)) {
6952                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6953                         goto out;
6954                 }
6955
6956                 result = fill_job_info2(info,
6957                                         &info[i].info2,
6958                                         &queue[i],
6959                                         i,
6960                                         snum,
6961                                         pinfo2,
6962                                         devmode);
6963                 if (!W_ERROR_IS_OK(result)) {
6964                         goto out;
6965                 }
6966         }
6967
6968  out:
6969         if (!W_ERROR_IS_OK(result)) {
6970                 TALLOC_FREE(info);
6971                 *count = 0;
6972                 return result;
6973         }
6974
6975         *info_p = info;
6976
6977         return WERR_OK;
6978 }
6979
6980 /****************************************************************************
6981  Enumjobs at level 3.
6982 ****************************************************************************/
6983
6984 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6985                               const print_queue_struct *queue,
6986                               uint32_t num_queues, int snum,
6987                               struct spoolss_PrinterInfo2 *pinfo2,
6988                               union spoolss_JobInfo **info_p,
6989                               uint32_t *count)
6990 {
6991         union spoolss_JobInfo *info;
6992         int i;
6993         WERROR result = WERR_OK;
6994
6995         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6996         W_ERROR_HAVE_NO_MEMORY(info);
6997
6998         *count = num_queues;
6999
7000         for (i=0; i<*count; i++) {
7001                 const print_queue_struct *next_queue = NULL;
7002
7003                 if (i+1 < *count) {
7004                         next_queue = &queue[i+1];
7005                 }
7006
7007                 result = fill_job_info3(info,
7008                                         &info[i].info3,
7009                                         &queue[i],
7010                                         next_queue,
7011                                         i,
7012                                         snum,
7013                                         pinfo2);
7014                 if (!W_ERROR_IS_OK(result)) {
7015                         goto out;
7016                 }
7017         }
7018
7019  out:
7020         if (!W_ERROR_IS_OK(result)) {
7021                 TALLOC_FREE(info);
7022                 *count = 0;
7023                 return result;
7024         }
7025
7026         *info_p = info;
7027
7028         return WERR_OK;
7029 }
7030
7031 /****************************************************************
7032  _spoolss_EnumJobs
7033 ****************************************************************/
7034
7035 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7036                          struct spoolss_EnumJobs *r)
7037 {
7038         WERROR result;
7039         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7040         int snum;
7041         print_status_struct prt_status;
7042         print_queue_struct *queue = NULL;
7043         uint32_t count;
7044
7045         /* that's an [in out] buffer */
7046
7047         if (!r->in.buffer && (r->in.offered != 0)) {
7048                 return WERR_INVALID_PARAM;
7049         }
7050
7051         DEBUG(4,("_spoolss_EnumJobs\n"));
7052
7053         *r->out.needed = 0;
7054         *r->out.count = 0;
7055         *r->out.info = NULL;
7056
7057         /* lookup the printer snum and tdb entry */
7058
7059         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7060                 return WERR_BADFID;
7061         }
7062
7063         result = winreg_get_printer(p->mem_ctx,
7064                                     get_session_info_system(),
7065                                     p->msg_ctx,
7066                                     lp_const_servicename(snum),
7067                                     &pinfo2);
7068         if (!W_ERROR_IS_OK(result)) {
7069                 return result;
7070         }
7071
7072         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7073         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7074                 count, prt_status.status, prt_status.message));
7075
7076         if (count == 0) {
7077                 SAFE_FREE(queue);
7078                 TALLOC_FREE(pinfo2);
7079                 return WERR_OK;
7080         }
7081
7082         switch (r->in.level) {
7083         case 1:
7084                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7085                                          pinfo2, r->out.info, r->out.count);
7086                 break;
7087         case 2:
7088                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7089                                          pinfo2, r->out.info, r->out.count);
7090                 break;
7091         case 3:
7092                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7093                                          pinfo2, r->out.info, r->out.count);
7094                 break;
7095         default:
7096                 result = WERR_UNKNOWN_LEVEL;
7097                 break;
7098         }
7099
7100         SAFE_FREE(queue);
7101         TALLOC_FREE(pinfo2);
7102
7103         if (!W_ERROR_IS_OK(result)) {
7104                 return result;
7105         }
7106
7107         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7108                                                      spoolss_EnumJobs,
7109                                                      *r->out.info, r->in.level,
7110                                                      *r->out.count);
7111         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7112         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7113
7114         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7115 }
7116
7117 /****************************************************************
7118  _spoolss_ScheduleJob
7119 ****************************************************************/
7120
7121 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7122                             struct spoolss_ScheduleJob *r)
7123 {
7124         return WERR_OK;
7125 }
7126
7127 /****************************************************************
7128 ****************************************************************/
7129
7130 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7131                                struct messaging_context *msg_ctx,
7132                                const char *printer_name,
7133                                uint32_t job_id,
7134                                struct spoolss_SetJobInfo1 *r)
7135 {
7136         char *old_doc_name;
7137
7138         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7139                 return WERR_BADFID;
7140         }
7141
7142         if (strequal(old_doc_name, r->document_name)) {
7143                 return WERR_OK;
7144         }
7145
7146         if (!print_job_set_name(server_event_context(), msg_ctx,
7147                                 printer_name, job_id, r->document_name)) {
7148                 return WERR_BADFID;
7149         }
7150
7151         return WERR_OK;
7152 }
7153
7154 /****************************************************************
7155  _spoolss_SetJob
7156 ****************************************************************/
7157
7158 WERROR _spoolss_SetJob(struct pipes_struct *p,
7159                        struct spoolss_SetJob *r)
7160 {
7161         const struct auth_serversupplied_info *session_info = p->session_info;
7162         int snum;
7163         WERROR errcode = WERR_BADFUNC;
7164
7165         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7166                 return WERR_BADFID;
7167         }
7168
7169         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7170                 return WERR_INVALID_PRINTER_NAME;
7171         }
7172
7173         switch (r->in.command) {
7174         case SPOOLSS_JOB_CONTROL_CANCEL:
7175         case SPOOLSS_JOB_CONTROL_DELETE:
7176                 errcode = print_job_delete(session_info, p->msg_ctx,
7177                                            snum, r->in.job_id);
7178                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7179                         errcode = WERR_OK;
7180                 }
7181                 break;
7182         case SPOOLSS_JOB_CONTROL_PAUSE:
7183                 if (print_job_pause(session_info, p->msg_ctx,
7184                                     snum, r->in.job_id, &errcode)) {
7185                         errcode = WERR_OK;
7186                 }
7187                 break;
7188         case SPOOLSS_JOB_CONTROL_RESTART:
7189         case SPOOLSS_JOB_CONTROL_RESUME:
7190                 if (print_job_resume(session_info, p->msg_ctx,
7191                                      snum, r->in.job_id, &errcode)) {
7192                         errcode = WERR_OK;
7193                 }
7194                 break;
7195         case 0:
7196                 errcode = WERR_OK;
7197                 break;
7198         default:
7199                 return WERR_UNKNOWN_LEVEL;
7200         }
7201
7202         if (!W_ERROR_IS_OK(errcode)) {
7203                 return errcode;
7204         }
7205
7206         if (r->in.ctr == NULL) {
7207                 return errcode;
7208         }
7209
7210         switch (r->in.ctr->level) {
7211         case 1:
7212                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7213                                            lp_const_servicename(snum),
7214                                            r->in.job_id,
7215                                            r->in.ctr->info.info1);
7216                 break;
7217         case 2:
7218         case 3:
7219         case 4:
7220         default:
7221                 return WERR_UNKNOWN_LEVEL;
7222         }
7223
7224         return errcode;
7225 }
7226
7227 /****************************************************************************
7228  Enumerates all printer drivers by level and architecture.
7229 ****************************************************************************/
7230
7231 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7232                                                        const struct auth_serversupplied_info *session_info,
7233                                                        struct messaging_context *msg_ctx,
7234                                                        const char *servername,
7235                                                        const char *architecture,
7236                                                        uint32_t level,
7237                                                        union spoolss_DriverInfo **info_p,
7238                                                        uint32_t *count_p)
7239 {
7240         int i;
7241         uint32_t version;
7242         struct spoolss_DriverInfo8 *driver;
7243         union spoolss_DriverInfo *info = NULL;
7244         uint32_t count = 0;
7245         WERROR result = WERR_OK;
7246         uint32_t num_drivers;
7247         const char **drivers;
7248
7249         *count_p = 0;
7250         *info_p = NULL;
7251
7252         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7253                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7254                                                 architecture, version,
7255                                                 &num_drivers, &drivers);
7256                 if (!W_ERROR_IS_OK(result)) {
7257                         goto out;
7258                 }
7259                 DEBUG(4, ("we have:[%d] drivers in environment"
7260                           " [%s] and version [%d]\n",
7261                           num_drivers, architecture, version));
7262
7263                 if (num_drivers != 0) {
7264                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7265                                                     union spoolss_DriverInfo,
7266                                                     count + num_drivers);
7267                         if (!info) {
7268                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7269                                         "failed to enlarge driver info buffer!\n"));
7270                                 result = WERR_NOMEM;
7271                                 goto out;
7272                         }
7273                 }
7274
7275                 for (i = 0; i < num_drivers; i++) {
7276                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7277
7278                         result = winreg_get_driver(mem_ctx, session_info,
7279                                                    msg_ctx,
7280                                                    architecture, drivers[i],
7281                                                    version, &driver);
7282                         if (!W_ERROR_IS_OK(result)) {
7283                                 goto out;
7284                         }
7285
7286                         switch (level) {
7287                         case 1:
7288                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7289                                                                    driver, servername);
7290                                 break;
7291                         case 2:
7292                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7293                                                                    driver, servername);
7294                                 break;
7295                         case 3:
7296                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7297                                                                    driver, servername);
7298                                 break;
7299                         case 4:
7300                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7301                                                                    driver, servername);
7302                                 break;
7303                         case 5:
7304                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7305                                                                    driver, servername);
7306                                 break;
7307                         case 6:
7308                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7309                                                                    driver, servername);
7310                                 break;
7311                         case 8:
7312                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7313                                                                    driver, servername);
7314                                 break;
7315                         default:
7316                                 result = WERR_UNKNOWN_LEVEL;
7317                                 break;
7318                         }
7319
7320                         TALLOC_FREE(driver);
7321
7322                         if (!W_ERROR_IS_OK(result)) {
7323                                 goto out;
7324                         }
7325                 }
7326
7327                 count += num_drivers;
7328                 TALLOC_FREE(drivers);
7329         }
7330
7331  out:
7332         TALLOC_FREE(drivers);
7333
7334         if (!W_ERROR_IS_OK(result)) {
7335                 TALLOC_FREE(info);
7336                 return result;
7337         }
7338
7339         *info_p = info;
7340         *count_p = count;
7341
7342         return WERR_OK;
7343 }
7344
7345 /****************************************************************************
7346  Enumerates all printer drivers by level.
7347 ****************************************************************************/
7348
7349 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7350                                        const struct auth_serversupplied_info *session_info,
7351                                        struct messaging_context *msg_ctx,
7352                                        const char *servername,
7353                                        const char *architecture,
7354                                        uint32_t level,
7355                                        union spoolss_DriverInfo **info_p,
7356                                        uint32_t *count_p)
7357 {
7358         uint32_t a,i;
7359         WERROR result = WERR_OK;
7360
7361         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7362
7363                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7364
7365                         union spoolss_DriverInfo *info = NULL;
7366                         uint32_t count = 0;
7367
7368                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7369                                                                           session_info,
7370                                                                           msg_ctx,
7371                                                                           servername,
7372                                                                           archi_table[a].long_archi,
7373                                                                           level,
7374                                                                           &info,
7375                                                                           &count);
7376                         if (!W_ERROR_IS_OK(result)) {
7377                                 continue;
7378                         }
7379
7380                         for (i=0; i < count; i++) {
7381                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7382                                              info[i], info_p, count_p);
7383                         }
7384                 }
7385
7386                 return result;
7387         }
7388
7389         return enumprinterdrivers_level_by_architecture(mem_ctx,
7390                                                         session_info,
7391                                                         msg_ctx,
7392                                                         servername,
7393                                                         architecture,
7394                                                         level,
7395                                                         info_p,
7396                                                         count_p);
7397 }
7398
7399 /****************************************************************
7400  _spoolss_EnumPrinterDrivers
7401 ****************************************************************/
7402
7403 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7404                                    struct spoolss_EnumPrinterDrivers *r)
7405 {
7406         const char *cservername;
7407         WERROR result;
7408
7409         /* that's an [in out] buffer */
7410
7411         if (!r->in.buffer && (r->in.offered != 0)) {
7412                 return WERR_INVALID_PARAM;
7413         }
7414
7415         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7416
7417         *r->out.needed = 0;
7418         *r->out.count = 0;
7419         *r->out.info = NULL;
7420
7421         cservername = canon_servername(r->in.server);
7422
7423         if (!is_myname_or_ipaddr(cservername)) {
7424                 return WERR_UNKNOWN_PRINTER_DRIVER;
7425         }
7426
7427         result = enumprinterdrivers_level(p->mem_ctx,
7428                                           get_session_info_system(),
7429                                           p->msg_ctx,
7430                                           cservername,
7431                                           r->in.environment,
7432                                           r->in.level,
7433                                           r->out.info,
7434                                           r->out.count);
7435         if (!W_ERROR_IS_OK(result)) {
7436                 return result;
7437         }
7438
7439         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7440                                                      spoolss_EnumPrinterDrivers,
7441                                                      *r->out.info, r->in.level,
7442                                                      *r->out.count);
7443         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7444         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7445
7446         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7447 }
7448
7449 /****************************************************************
7450  _spoolss_EnumForms
7451 ****************************************************************/
7452
7453 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7454                           struct spoolss_EnumForms *r)
7455 {
7456         WERROR result;
7457
7458         *r->out.count = 0;
7459         *r->out.needed = 0;
7460         *r->out.info = NULL;
7461
7462         /* that's an [in out] buffer */
7463
7464         if (!r->in.buffer && (r->in.offered != 0) ) {
7465                 return WERR_INVALID_PARAM;
7466         }
7467
7468         DEBUG(4,("_spoolss_EnumForms\n"));
7469         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7470         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7471
7472         switch (r->in.level) {
7473         case 1:
7474                 result = winreg_printer_enumforms1(p->mem_ctx,
7475                                                    get_session_info_system(),
7476                                                    p->msg_ctx,
7477                                                    r->out.count,
7478                                                    r->out.info);
7479                 break;
7480         default:
7481                 result = WERR_UNKNOWN_LEVEL;
7482                 break;
7483         }
7484
7485         if (!W_ERROR_IS_OK(result)) {
7486                 return result;
7487         }
7488
7489         if (*r->out.count == 0) {
7490                 return WERR_NO_MORE_ITEMS;
7491         }
7492
7493         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7494                                                      spoolss_EnumForms,
7495                                                      *r->out.info, r->in.level,
7496                                                      *r->out.count);
7497         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7498         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7499
7500         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7501 }
7502
7503 /****************************************************************
7504  _spoolss_GetForm
7505 ****************************************************************/
7506
7507 WERROR _spoolss_GetForm(struct pipes_struct *p,
7508                         struct spoolss_GetForm *r)
7509 {
7510         WERROR result;
7511
7512         /* that's an [in out] buffer */
7513
7514         if (!r->in.buffer && (r->in.offered != 0)) {
7515                 return WERR_INVALID_PARAM;
7516         }
7517
7518         DEBUG(4,("_spoolss_GetForm\n"));
7519         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7520         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7521
7522         switch (r->in.level) {
7523         case 1:
7524                 result = winreg_printer_getform1(p->mem_ctx,
7525                                                  get_session_info_system(),
7526                                                  p->msg_ctx,
7527                                                  r->in.form_name,
7528                                                  &r->out.info->info1);
7529                 break;
7530         default:
7531                 result = WERR_UNKNOWN_LEVEL;
7532                 break;
7533         }
7534
7535         if (!W_ERROR_IS_OK(result)) {
7536                 TALLOC_FREE(r->out.info);
7537                 return result;
7538         }
7539
7540         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7541                                                r->out.info, r->in.level);
7542         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7543
7544         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7545 }
7546
7547 /****************************************************************************
7548 ****************************************************************************/
7549
7550 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7551                           struct spoolss_PortInfo1 *r,
7552                           const char *name)
7553 {
7554         r->port_name = talloc_strdup(mem_ctx, name);
7555         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7556
7557         return WERR_OK;
7558 }
7559
7560 /****************************************************************************
7561  TODO: This probably needs distinguish between TCP/IP and Local ports
7562  somehow.
7563 ****************************************************************************/
7564
7565 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7566                           struct spoolss_PortInfo2 *r,
7567                           const char *name)
7568 {
7569         r->port_name = talloc_strdup(mem_ctx, name);
7570         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7571
7572         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7573         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7574
7575         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7576         W_ERROR_HAVE_NO_MEMORY(r->description);
7577
7578         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7579         r->reserved = 0;
7580
7581         return WERR_OK;
7582 }
7583
7584
7585 /****************************************************************************
7586  wrapper around the enumer ports command
7587 ****************************************************************************/
7588
7589 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7590 {
7591         char *cmd = lp_enumports_cmd();
7592         char **qlines = NULL;
7593         char *command = NULL;
7594         int numlines;
7595         int ret;
7596         int fd;
7597
7598         *count = 0;
7599         *lines = NULL;
7600
7601         /* if no hook then just fill in the default port */
7602
7603         if ( !*cmd ) {
7604                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7605                         return WERR_NOMEM;
7606                 }
7607                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7608                         TALLOC_FREE(qlines);
7609                         return WERR_NOMEM;
7610                 }
7611                 qlines[1] = NULL;
7612                 numlines = 1;
7613         }
7614         else {
7615                 /* we have a valid enumport command */
7616
7617                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7618                 if (!command) {
7619                         return WERR_NOMEM;
7620                 }
7621
7622                 DEBUG(10,("Running [%s]\n", command));
7623                 ret = smbrun(command, &fd);
7624                 DEBUG(10,("Returned [%d]\n", ret));
7625                 TALLOC_FREE(command);
7626                 if (ret != 0) {
7627                         if (fd != -1) {
7628                                 close(fd);
7629                         }
7630                         return WERR_ACCESS_DENIED;
7631                 }
7632
7633                 numlines = 0;
7634                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7635                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7636                 close(fd);
7637         }
7638
7639         *count = numlines;
7640         *lines = qlines;
7641
7642         return WERR_OK;
7643 }
7644
7645 /****************************************************************************
7646  enumports level 1.
7647 ****************************************************************************/
7648
7649 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7650                                 union spoolss_PortInfo **info_p,
7651                                 uint32_t *count)
7652 {
7653         union spoolss_PortInfo *info = NULL;
7654         int i=0;
7655         WERROR result = WERR_OK;
7656         char **qlines = NULL;
7657         int numlines = 0;
7658
7659         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7660         if (!W_ERROR_IS_OK(result)) {
7661                 goto out;
7662         }
7663
7664         if (numlines) {
7665                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7666                 if (!info) {
7667                         DEBUG(10,("Returning WERR_NOMEM\n"));
7668                         result = WERR_NOMEM;
7669                         goto out;
7670                 }
7671
7672                 for (i=0; i<numlines; i++) {
7673                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7674                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7675                         if (!W_ERROR_IS_OK(result)) {
7676                                 goto out;
7677                         }
7678                 }
7679         }
7680         TALLOC_FREE(qlines);
7681
7682 out:
7683         if (!W_ERROR_IS_OK(result)) {
7684                 TALLOC_FREE(info);
7685                 TALLOC_FREE(qlines);
7686                 *count = 0;
7687                 *info_p = NULL;
7688                 return result;
7689         }
7690
7691         *info_p = info;
7692         *count = numlines;
7693
7694         return WERR_OK;
7695 }
7696
7697 /****************************************************************************
7698  enumports level 2.
7699 ****************************************************************************/
7700
7701 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7702                                 union spoolss_PortInfo **info_p,
7703                                 uint32_t *count)
7704 {
7705         union spoolss_PortInfo *info = NULL;
7706         int i=0;
7707         WERROR result = WERR_OK;
7708         char **qlines = NULL;
7709         int numlines = 0;
7710
7711         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7712         if (!W_ERROR_IS_OK(result)) {
7713                 goto out;
7714         }
7715
7716         if (numlines) {
7717                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7718                 if (!info) {
7719                         DEBUG(10,("Returning WERR_NOMEM\n"));
7720                         result = WERR_NOMEM;
7721                         goto out;
7722                 }
7723
7724                 for (i=0; i<numlines; i++) {
7725                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7726                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7727                         if (!W_ERROR_IS_OK(result)) {
7728                                 goto out;
7729                         }
7730                 }
7731         }
7732         TALLOC_FREE(qlines);
7733
7734 out:
7735         if (!W_ERROR_IS_OK(result)) {
7736                 TALLOC_FREE(info);
7737                 TALLOC_FREE(qlines);
7738                 *count = 0;
7739                 *info_p = NULL;
7740                 return result;
7741         }
7742
7743         *info_p = info;
7744         *count = numlines;
7745
7746         return WERR_OK;
7747 }
7748
7749 /****************************************************************
7750  _spoolss_EnumPorts
7751 ****************************************************************/
7752
7753 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7754                           struct spoolss_EnumPorts *r)
7755 {
7756         WERROR result;
7757
7758         /* that's an [in out] buffer */
7759
7760         if (!r->in.buffer && (r->in.offered != 0)) {
7761                 return WERR_INVALID_PARAM;
7762         }
7763
7764         DEBUG(4,("_spoolss_EnumPorts\n"));
7765
7766         *r->out.count = 0;
7767         *r->out.needed = 0;
7768         *r->out.info = NULL;
7769
7770         switch (r->in.level) {
7771         case 1:
7772                 result = enumports_level_1(p->mem_ctx, r->out.info,
7773                                            r->out.count);
7774                 break;
7775         case 2:
7776                 result = enumports_level_2(p->mem_ctx, r->out.info,
7777                                            r->out.count);
7778                 break;
7779         default:
7780                 return WERR_UNKNOWN_LEVEL;
7781         }
7782
7783         if (!W_ERROR_IS_OK(result)) {
7784                 return result;
7785         }
7786
7787         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7788                                                      spoolss_EnumPorts,
7789                                                      *r->out.info, r->in.level,
7790                                                      *r->out.count);
7791         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7792         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7793
7794         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7795 }
7796
7797 /****************************************************************************
7798 ****************************************************************************/
7799
7800 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7801                                            const char *server,
7802                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7803                                            struct spoolss_DeviceMode *devmode,
7804                                            struct security_descriptor *secdesc,
7805                                            struct spoolss_UserLevelCtr *user_ctr,
7806                                            struct policy_handle *handle)
7807 {
7808         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7809         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7810         int     snum;
7811         WERROR err = WERR_OK;
7812
7813         /* samba does not have a concept of local, non-shared printers yet, so
7814          * make sure we always setup sharename - gd */
7815         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7816             (info2->printername != NULL && info2->printername[0] != '\0')) {
7817                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7818                         "no sharename has been set, setting printername %s as sharename\n",
7819                         info2->printername));
7820                 info2->sharename = info2->printername;
7821         }
7822
7823         /* check to see if the printer already exists */
7824         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7825                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7826                         info2->sharename));
7827                 return WERR_PRINTER_ALREADY_EXISTS;
7828         }
7829
7830         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7831                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7832                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7833                                 info2->printername));
7834                         return WERR_PRINTER_ALREADY_EXISTS;
7835                 }
7836         }
7837
7838         /* validate printer info struct */
7839         if (!info2->printername || strlen(info2->printername) == 0) {
7840                 return WERR_INVALID_PRINTER_NAME;
7841         }
7842         if (!info2->portname || strlen(info2->portname) == 0) {
7843                 return WERR_UNKNOWN_PORT;
7844         }
7845         if (!info2->drivername || strlen(info2->drivername) == 0) {
7846                 return WERR_UNKNOWN_PRINTER_DRIVER;
7847         }
7848         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7849                 return WERR_UNKNOWN_PRINTPROCESSOR;
7850         }
7851
7852         /* FIXME!!!  smbd should check to see if the driver is installed before
7853            trying to add a printer like this  --jerry */
7854
7855         if (*lp_addprinter_cmd() ) {
7856                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7857                                        info2, p->client_id->addr,
7858                                        p->msg_ctx) ) {
7859                         return WERR_ACCESS_DENIED;
7860                 }
7861         } else {
7862                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7863                         "smb.conf parameter \"addprinter command\" is defined. This "
7864                         "parameter must exist for this call to succeed\n",
7865                         info2->sharename ));
7866         }
7867
7868         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7869                 return WERR_ACCESS_DENIED;
7870         }
7871
7872         /* you must be a printer admin to add a new printer */
7873         if (!print_access_check(p->session_info,
7874                                 p->msg_ctx,
7875                                 snum,
7876                                 PRINTER_ACCESS_ADMINISTER)) {
7877                 return WERR_ACCESS_DENIED;
7878         }
7879
7880         /*
7881          * Do sanity check on the requested changes for Samba.
7882          */
7883
7884         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7885                 return WERR_INVALID_PARAM;
7886         }
7887
7888         if (devmode == NULL) {
7889                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7890         }
7891
7892         update_dsspooler(p->mem_ctx,
7893                          get_session_info_system(),
7894                          p->msg_ctx,
7895                          0,
7896                          info2,
7897                          NULL);
7898
7899         err = winreg_update_printer(p->mem_ctx,
7900                                     get_session_info_system(),
7901                                     p->msg_ctx,
7902                                     info2->sharename,
7903                                     info2_mask,
7904                                     info2,
7905                                     devmode,
7906                                     secdesc);
7907         if (!W_ERROR_IS_OK(err)) {
7908                 return err;
7909         }
7910
7911         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7912         if (!W_ERROR_IS_OK(err)) {
7913                 /* Handle open failed - remove addition. */
7914                 ZERO_STRUCTP(handle);
7915                 return err;
7916         }
7917
7918         return WERR_OK;
7919 }
7920
7921 /****************************************************************
7922  _spoolss_AddPrinterEx
7923 ****************************************************************/
7924
7925 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7926                              struct spoolss_AddPrinterEx *r)
7927 {
7928         switch (r->in.info_ctr->level) {
7929         case 1:
7930                 /* we don't handle yet */
7931                 /* but I know what to do ... */
7932                 return WERR_UNKNOWN_LEVEL;
7933         case 2:
7934                 return spoolss_addprinterex_level_2(p, r->in.server,
7935                                                     r->in.info_ctr,
7936                                                     r->in.devmode_ctr->devmode,
7937                                                     r->in.secdesc_ctr->sd,
7938                                                     r->in.userlevel_ctr,
7939                                                     r->out.handle);
7940         default:
7941                 return WERR_UNKNOWN_LEVEL;
7942         }
7943 }
7944
7945 /****************************************************************
7946  _spoolss_AddPrinter
7947 ****************************************************************/
7948
7949 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7950                            struct spoolss_AddPrinter *r)
7951 {
7952         struct spoolss_AddPrinterEx a;
7953         struct spoolss_UserLevelCtr userlevel_ctr;
7954
7955         ZERO_STRUCT(userlevel_ctr);
7956
7957         userlevel_ctr.level = 1;
7958
7959         a.in.server             = r->in.server;
7960         a.in.info_ctr           = r->in.info_ctr;
7961         a.in.devmode_ctr        = r->in.devmode_ctr;
7962         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7963         a.in.userlevel_ctr      = &userlevel_ctr;
7964         a.out.handle            = r->out.handle;
7965
7966         return _spoolss_AddPrinterEx(p, &a);
7967 }
7968
7969 /****************************************************************
7970  _spoolss_AddPrinterDriverEx
7971 ****************************************************************/
7972
7973 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7974                                    struct spoolss_AddPrinterDriverEx *r)
7975 {
7976         WERROR err = WERR_OK;
7977         const char *driver_name = NULL;
7978         uint32_t version;
7979         const char *fn;
7980
7981         switch (p->opnum) {
7982                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7983                         fn = "_spoolss_AddPrinterDriver";
7984                         break;
7985                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7986                         fn = "_spoolss_AddPrinterDriverEx";
7987                         break;
7988                 default:
7989                         return WERR_INVALID_PARAM;
7990         }
7991
7992         /*
7993          * we only support the semantics of AddPrinterDriver()
7994          * i.e. only copy files that are newer than existing ones
7995          */
7996
7997         if (r->in.flags == 0) {
7998                 return WERR_INVALID_PARAM;
7999         }
8000
8001         if (r->in.flags != APD_COPY_NEW_FILES) {
8002                 return WERR_ACCESS_DENIED;
8003         }
8004
8005         /* FIXME */
8006         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8007                 /* Clever hack from Martin Zielinski <mz@seh.de>
8008                  * to allow downgrade from level 8 (Vista).
8009                  */
8010                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8011                         r->in.info_ctr->level));
8012                 return WERR_UNKNOWN_LEVEL;
8013         }
8014
8015         DEBUG(5,("Cleaning driver's information\n"));
8016         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8017         if (!W_ERROR_IS_OK(err))
8018                 goto done;
8019
8020         DEBUG(5,("Moving driver to final destination\n"));
8021         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8022         if (!W_ERROR_IS_OK(err)) {
8023                 goto done;
8024         }
8025
8026         err = winreg_add_driver(p->mem_ctx,
8027                                 get_session_info_system(),
8028                                 p->msg_ctx,
8029                                 r->in.info_ctr,
8030                                 &driver_name,
8031                                 &version);
8032         if (!W_ERROR_IS_OK(err)) {
8033                 goto done;
8034         }
8035
8036         /*
8037          * I think this is where he DrvUpgradePrinter() hook would be
8038          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8039          * server.  Right now, we just need to send ourselves a message
8040          * to update each printer bound to this driver.   --jerry
8041          */
8042
8043         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8044                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8045                         fn, driver_name));
8046         }
8047
8048 done:
8049         return err;
8050 }
8051
8052 /****************************************************************
8053  _spoolss_AddPrinterDriver
8054 ****************************************************************/
8055
8056 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8057                                  struct spoolss_AddPrinterDriver *r)
8058 {
8059         struct spoolss_AddPrinterDriverEx a;
8060
8061         switch (r->in.info_ctr->level) {
8062         case 2:
8063         case 3:
8064         case 4:
8065         case 5:
8066                 break;
8067         default:
8068                 return WERR_UNKNOWN_LEVEL;
8069         }
8070
8071         a.in.servername         = r->in.servername;
8072         a.in.info_ctr           = r->in.info_ctr;
8073         a.in.flags              = APD_COPY_NEW_FILES;
8074
8075         return _spoolss_AddPrinterDriverEx(p, &a);
8076 }
8077
8078 /****************************************************************************
8079 ****************************************************************************/
8080
8081 struct _spoolss_paths {
8082         int type;
8083         const char *share;
8084         const char *dir;
8085 };
8086
8087 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8088
8089 static const struct _spoolss_paths spoolss_paths[]= {
8090         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8091         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8092 };
8093
8094 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8095                                           const char *servername,
8096                                           const char *environment,
8097                                           int component,
8098                                           char **path)
8099 {
8100         const char *pservername = NULL;
8101         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8102         const char *short_archi;
8103
8104         *path = NULL;
8105
8106         /* environment may be empty */
8107         if (environment && strlen(environment)) {
8108                 long_archi = environment;
8109         }
8110
8111         /* servername may be empty */
8112         if (servername && strlen(servername)) {
8113                 pservername = canon_servername(servername);
8114
8115                 if (!is_myname_or_ipaddr(pservername)) {
8116                         return WERR_INVALID_PARAM;
8117                 }
8118         }
8119
8120         if (!(short_archi = get_short_archi(long_archi))) {
8121                 return WERR_INVALID_ENVIRONMENT;
8122         }
8123
8124         switch (component) {
8125         case SPOOLSS_PRTPROCS_PATH:
8126         case SPOOLSS_DRIVER_PATH:
8127                 if (pservername) {
8128                         *path = talloc_asprintf(mem_ctx,
8129                                         "\\\\%s\\%s\\%s",
8130                                         pservername,
8131                                         spoolss_paths[component].share,
8132                                         short_archi);
8133                 } else {
8134                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8135                                         SPOOLSS_DEFAULT_SERVER_PATH,
8136                                         spoolss_paths[component].dir,
8137                                         short_archi);
8138                 }
8139                 break;
8140         default:
8141                 return WERR_INVALID_PARAM;
8142         }
8143
8144         if (!*path) {
8145                 return WERR_NOMEM;
8146         }
8147
8148         return WERR_OK;
8149 }
8150
8151 /****************************************************************************
8152 ****************************************************************************/
8153
8154 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8155                                           const char *servername,
8156                                           const char *environment,
8157                                           struct spoolss_DriverDirectoryInfo1 *r)
8158 {
8159         WERROR werr;
8160         char *path = NULL;
8161
8162         werr = compose_spoolss_server_path(mem_ctx,
8163                                            servername,
8164                                            environment,
8165                                            SPOOLSS_DRIVER_PATH,
8166                                            &path);
8167         if (!W_ERROR_IS_OK(werr)) {
8168                 return werr;
8169         }
8170
8171         DEBUG(4,("printer driver directory: [%s]\n", path));
8172
8173         r->directory_name = path;
8174
8175         return WERR_OK;
8176 }
8177
8178 /****************************************************************
8179  _spoolss_GetPrinterDriverDirectory
8180 ****************************************************************/
8181
8182 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8183                                           struct spoolss_GetPrinterDriverDirectory *r)
8184 {
8185         WERROR werror;
8186
8187         /* that's an [in out] buffer */
8188
8189         if (!r->in.buffer && (r->in.offered != 0)) {
8190                 return WERR_INVALID_PARAM;
8191         }
8192
8193         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8194                 r->in.level));
8195
8196         *r->out.needed = 0;
8197
8198         /* r->in.level is ignored */
8199
8200         werror = getprinterdriverdir_level_1(p->mem_ctx,
8201                                              r->in.server,
8202                                              r->in.environment,
8203                                              &r->out.info->info1);
8204         if (!W_ERROR_IS_OK(werror)) {
8205                 TALLOC_FREE(r->out.info);
8206                 return werror;
8207         }
8208
8209         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8210                                                r->out.info, r->in.level);
8211         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8212
8213         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8214 }
8215
8216 /****************************************************************
8217  _spoolss_EnumPrinterData
8218 ****************************************************************/
8219
8220 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8221                                 struct spoolss_EnumPrinterData *r)
8222 {
8223         WERROR result;
8224         struct spoolss_EnumPrinterDataEx r2;
8225         uint32_t count;
8226         struct spoolss_PrinterEnumValues *info, *val = NULL;
8227         uint32_t needed;
8228
8229         r2.in.handle    = r->in.handle;
8230         r2.in.key_name  = "PrinterDriverData";
8231         r2.in.offered   = 0;
8232         r2.out.count    = &count;
8233         r2.out.info     = &info;
8234         r2.out.needed   = &needed;
8235
8236         result = _spoolss_EnumPrinterDataEx(p, &r2);
8237         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8238                 r2.in.offered = needed;
8239                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8240         }
8241         if (!W_ERROR_IS_OK(result)) {
8242                 return result;
8243         }
8244
8245         /*
8246          * The NT machine wants to know the biggest size of value and data
8247          *
8248          * cf: MSDN EnumPrinterData remark section
8249          */
8250
8251         if (!r->in.value_offered && !r->in.data_offered) {
8252                 uint32_t biggest_valuesize = 0;
8253                 uint32_t biggest_datasize = 0;
8254                 int i, name_length;
8255
8256                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8257
8258                 for (i=0; i<count; i++) {
8259
8260                         name_length = strlen(info[i].value_name);
8261                         if (strlen(info[i].value_name) > biggest_valuesize) {
8262                                 biggest_valuesize = name_length;
8263                         }
8264
8265                         if (info[i].data_length > biggest_datasize) {
8266                                 biggest_datasize = info[i].data_length;
8267                         }
8268
8269                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8270                                 biggest_datasize));
8271                 }
8272
8273                 /* the value is an UNICODE string but real_value_size is the length
8274                    in bytes including the trailing 0 */
8275
8276                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8277                 *r->out.data_needed  = biggest_datasize;
8278
8279                 DEBUG(6,("final values: [%d], [%d]\n",
8280                         *r->out.value_needed, *r->out.data_needed));
8281
8282                 return WERR_OK;
8283         }
8284
8285         if (r->in.enum_index < count) {
8286                 val = &info[r->in.enum_index];
8287         }
8288
8289         if (val == NULL) {
8290                 /* out_value should default to "" or else NT4 has
8291                    problems unmarshalling the response */
8292
8293                 if (r->in.value_offered) {
8294                         *r->out.value_needed = 1;
8295                         r->out.value_name = talloc_strdup(r, "");
8296                         if (!r->out.value_name) {
8297                                 return WERR_NOMEM;
8298                         }
8299                 } else {
8300                         r->out.value_name = NULL;
8301                         *r->out.value_needed = 0;
8302                 }
8303
8304                 /* the data is counted in bytes */
8305
8306                 *r->out.data_needed = r->in.data_offered;
8307
8308                 result = WERR_NO_MORE_ITEMS;
8309         } else {
8310                 /*
8311                  * the value is:
8312                  * - counted in bytes in the request
8313                  * - counted in UNICODE chars in the max reply
8314                  * - counted in bytes in the real size
8315                  *
8316                  * take a pause *before* coding not *during* coding
8317                  */
8318
8319                 /* name */
8320                 if (r->in.value_offered) {
8321                         r->out.value_name = talloc_strdup(r, val->value_name);
8322                         if (!r->out.value_name) {
8323                                 return WERR_NOMEM;
8324                         }
8325                         *r->out.value_needed = val->value_name_len;
8326                 } else {
8327                         r->out.value_name = NULL;
8328                         *r->out.value_needed = 0;
8329                 }
8330
8331                 /* type */
8332
8333                 *r->out.type = val->type;
8334
8335                 /* data - counted in bytes */
8336
8337                 /*
8338                  * See the section "Dynamically Typed Query Parameters"
8339                  * in MS-RPRN.
8340                  */
8341
8342                 if (r->out.data && val->data && val->data->data &&
8343                                 val->data_length && r->in.data_offered) {
8344                         memcpy(r->out.data, val->data->data,
8345                                 MIN(val->data_length,r->in.data_offered));
8346                 }
8347
8348                 *r->out.data_needed = val->data_length;
8349
8350                 result = WERR_OK;
8351         }
8352
8353         return result;
8354 }
8355
8356 /****************************************************************
8357  _spoolss_SetPrinterData
8358 ****************************************************************/
8359
8360 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8361                                struct spoolss_SetPrinterData *r)
8362 {
8363         struct spoolss_SetPrinterDataEx r2;
8364
8365         r2.in.handle            = r->in.handle;
8366         r2.in.key_name          = "PrinterDriverData";
8367         r2.in.value_name        = r->in.value_name;
8368         r2.in.type              = r->in.type;
8369         r2.in.data              = r->in.data;
8370         r2.in.offered           = r->in.offered;
8371
8372         return _spoolss_SetPrinterDataEx(p, &r2);
8373 }
8374
8375 /****************************************************************
8376  _spoolss_ResetPrinter
8377 ****************************************************************/
8378
8379 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8380                              struct spoolss_ResetPrinter *r)
8381 {
8382         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8383         int             snum;
8384
8385         DEBUG(5,("_spoolss_ResetPrinter\n"));
8386
8387         /*
8388          * All we do is to check to see if the handle and queue is valid.
8389          * This call really doesn't mean anything to us because we only
8390          * support RAW printing.   --jerry
8391          */
8392
8393         if (!Printer) {
8394                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8395                         OUR_HANDLE(r->in.handle)));
8396                 return WERR_BADFID;
8397         }
8398
8399         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8400                 return WERR_BADFID;
8401
8402
8403         /* blindly return success */
8404         return WERR_OK;
8405 }
8406
8407 /****************************************************************
8408  _spoolss_DeletePrinterData
8409 ****************************************************************/
8410
8411 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8412                                   struct spoolss_DeletePrinterData *r)
8413 {
8414         struct spoolss_DeletePrinterDataEx r2;
8415
8416         r2.in.handle            = r->in.handle;
8417         r2.in.key_name          = "PrinterDriverData";
8418         r2.in.value_name        = r->in.value_name;
8419
8420         return _spoolss_DeletePrinterDataEx(p, &r2);
8421 }
8422
8423 /****************************************************************
8424  _spoolss_AddForm
8425 ****************************************************************/
8426
8427 WERROR _spoolss_AddForm(struct pipes_struct *p,
8428                         struct spoolss_AddForm *r)
8429 {
8430         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8431         int snum = -1;
8432         WERROR status = WERR_OK;
8433
8434         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8435
8436         DEBUG(5,("_spoolss_AddForm\n"));
8437
8438         if (!Printer) {
8439                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8440                         OUR_HANDLE(r->in.handle)));
8441                 return WERR_BADFID;
8442         }
8443
8444         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8445            and not a printer admin, then fail */
8446
8447         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8448             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8449             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8450                                           p->session_info->info3->base.domain.string,
8451                                           NULL,
8452                                           p->session_info->security_token,
8453                                           lp_printer_admin(snum))) {
8454                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8455                 return WERR_ACCESS_DENIED;
8456         }
8457
8458         switch (form->flags) {
8459         case SPOOLSS_FORM_USER:
8460         case SPOOLSS_FORM_BUILTIN:
8461         case SPOOLSS_FORM_PRINTER:
8462                 break;
8463         default:
8464                 return WERR_INVALID_PARAM;
8465         }
8466
8467         status = winreg_printer_addform1(p->mem_ctx,
8468                                          get_session_info_system(),
8469                                          p->msg_ctx,
8470                                          form);
8471         if (!W_ERROR_IS_OK(status)) {
8472                 return status;
8473         }
8474
8475         /*
8476          * ChangeID must always be set if this is a printer
8477          */
8478         if (Printer->printer_type == SPLHND_PRINTER) {
8479                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8480                         return WERR_BADFID;
8481                 }
8482
8483                 status = winreg_printer_update_changeid(p->mem_ctx,
8484                                                         get_session_info_system(),
8485                                                         p->msg_ctx,
8486                                                         lp_const_servicename(snum));
8487                 if (!W_ERROR_IS_OK(status)) {
8488                         return status;
8489                 }
8490         }
8491
8492         return status;
8493 }
8494
8495 /****************************************************************
8496  _spoolss_DeleteForm
8497 ****************************************************************/
8498
8499 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8500                            struct spoolss_DeleteForm *r)
8501 {
8502         const char *form_name = r->in.form_name;
8503         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8504         int snum = -1;
8505         WERROR status = WERR_OK;
8506
8507         DEBUG(5,("_spoolss_DeleteForm\n"));
8508
8509         if (!Printer) {
8510                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8511                         OUR_HANDLE(r->in.handle)));
8512                 return WERR_BADFID;
8513         }
8514
8515         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8516             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8517             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8518                                           p->session_info->info3->base.domain.string,
8519                                           NULL,
8520                                           p->session_info->security_token,
8521                                           lp_printer_admin(snum))) {
8522                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8523                 return WERR_ACCESS_DENIED;
8524         }
8525
8526         status = winreg_printer_deleteform1(p->mem_ctx,
8527                                             get_session_info_system(),
8528                                             p->msg_ctx,
8529                                             form_name);
8530         if (!W_ERROR_IS_OK(status)) {
8531                 return status;
8532         }
8533
8534         /*
8535          * ChangeID must always be set if this is a printer
8536          */
8537         if (Printer->printer_type == SPLHND_PRINTER) {
8538                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8539                         return WERR_BADFID;
8540                 }
8541
8542                 status = winreg_printer_update_changeid(p->mem_ctx,
8543                                                         get_session_info_system(),
8544                                                         p->msg_ctx,
8545                                                         lp_const_servicename(snum));
8546                 if (!W_ERROR_IS_OK(status)) {
8547                         return status;
8548                 }
8549         }
8550
8551         return status;
8552 }
8553
8554 /****************************************************************
8555  _spoolss_SetForm
8556 ****************************************************************/
8557
8558 WERROR _spoolss_SetForm(struct pipes_struct *p,
8559                         struct spoolss_SetForm *r)
8560 {
8561         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8562         const char *form_name = r->in.form_name;
8563         int snum = -1;
8564         WERROR status = WERR_OK;
8565
8566         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8567
8568         DEBUG(5,("_spoolss_SetForm\n"));
8569
8570         if (!Printer) {
8571                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8572                         OUR_HANDLE(r->in.handle)));
8573                 return WERR_BADFID;
8574         }
8575
8576         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8577            and not a printer admin, then fail */
8578
8579         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8580              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8581              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8582                                           p->session_info->info3->base.domain.string,
8583                                           NULL,
8584                                           p->session_info->security_token,
8585                                           lp_printer_admin(snum))) {
8586                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8587                 return WERR_ACCESS_DENIED;
8588         }
8589
8590         status = winreg_printer_setform1(p->mem_ctx,
8591                                          get_session_info_system(),
8592                                          p->msg_ctx,
8593                                          form_name,
8594                                          form);
8595         if (!W_ERROR_IS_OK(status)) {
8596                 return status;
8597         }
8598
8599         /*
8600          * ChangeID must always be set if this is a printer
8601          */
8602         if (Printer->printer_type == SPLHND_PRINTER) {
8603                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8604                         return WERR_BADFID;
8605                 }
8606
8607                 status = winreg_printer_update_changeid(p->mem_ctx,
8608                                                         get_session_info_system(),
8609                                                         p->msg_ctx,
8610                                                         lp_const_servicename(snum));
8611                 if (!W_ERROR_IS_OK(status)) {
8612                         return status;
8613                 }
8614         }
8615
8616         return status;
8617 }
8618
8619 /****************************************************************************
8620  fill_print_processor1
8621 ****************************************************************************/
8622
8623 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8624                                     struct spoolss_PrintProcessorInfo1 *r,
8625                                     const char *print_processor_name)
8626 {
8627         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8628         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8629
8630         return WERR_OK;
8631 }
8632
8633 /****************************************************************************
8634  enumprintprocessors level 1.
8635 ****************************************************************************/
8636
8637 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8638                                           union spoolss_PrintProcessorInfo **info_p,
8639                                           uint32_t *count)
8640 {
8641         union spoolss_PrintProcessorInfo *info;
8642         WERROR result;
8643
8644         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8645         W_ERROR_HAVE_NO_MEMORY(info);
8646
8647         *count = 1;
8648
8649         result = fill_print_processor1(info, &info[0].info1, "winprint");
8650         if (!W_ERROR_IS_OK(result)) {
8651                 goto out;
8652         }
8653
8654  out:
8655         if (!W_ERROR_IS_OK(result)) {
8656                 TALLOC_FREE(info);
8657                 *count = 0;
8658                 return result;
8659         }
8660
8661         *info_p = info;
8662
8663         return WERR_OK;
8664 }
8665
8666 /****************************************************************
8667  _spoolss_EnumPrintProcessors
8668 ****************************************************************/
8669
8670 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8671                                     struct spoolss_EnumPrintProcessors *r)
8672 {
8673         WERROR result;
8674
8675         /* that's an [in out] buffer */
8676
8677         if (!r->in.buffer && (r->in.offered != 0)) {
8678                 return WERR_INVALID_PARAM;
8679         }
8680
8681         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8682
8683         /*
8684          * Enumerate the print processors ...
8685          *
8686          * Just reply with "winprint", to keep NT happy
8687          * and I can use my nice printer checker.
8688          */
8689
8690         *r->out.count = 0;
8691         *r->out.needed = 0;
8692         *r->out.info = NULL;
8693
8694         if (!get_short_archi(r->in.environment)) {
8695                 return WERR_INVALID_ENVIRONMENT;
8696         }
8697
8698         switch (r->in.level) {
8699         case 1:
8700                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8701                                                      r->out.count);
8702                 break;
8703         default:
8704                 return WERR_UNKNOWN_LEVEL;
8705         }
8706
8707         if (!W_ERROR_IS_OK(result)) {
8708                 return result;
8709         }
8710
8711         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8712                                                      spoolss_EnumPrintProcessors,
8713                                                      *r->out.info, r->in.level,
8714                                                      *r->out.count);
8715         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8716         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8717
8718         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8719 }
8720
8721 /****************************************************************************
8722  fill_printprocdatatype1
8723 ****************************************************************************/
8724
8725 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8726                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8727                                       const char *name_array)
8728 {
8729         r->name_array = talloc_strdup(mem_ctx, name_array);
8730         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8731
8732         return WERR_OK;
8733 }
8734
8735 /****************************************************************************
8736  enumprintprocdatatypes level 1.
8737 ****************************************************************************/
8738
8739 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8740                                              union spoolss_PrintProcDataTypesInfo **info_p,
8741                                              uint32_t *count)
8742 {
8743         WERROR result;
8744         union spoolss_PrintProcDataTypesInfo *info;
8745
8746         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8747         W_ERROR_HAVE_NO_MEMORY(info);
8748
8749         *count = 1;
8750
8751         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8752         if (!W_ERROR_IS_OK(result)) {
8753                 goto out;
8754         }
8755
8756  out:
8757         if (!W_ERROR_IS_OK(result)) {
8758                 TALLOC_FREE(info);
8759                 *count = 0;
8760                 return result;
8761         }
8762
8763         *info_p = info;
8764
8765         return WERR_OK;
8766 }
8767
8768 /****************************************************************
8769  _spoolss_EnumPrintProcDataTypes
8770 ****************************************************************/
8771
8772 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8773                                        struct spoolss_EnumPrintProcDataTypes *r)
8774 {
8775         WERROR result;
8776
8777         /* that's an [in out] buffer */
8778
8779         if (!r->in.buffer && (r->in.offered != 0)) {
8780                 return WERR_INVALID_PARAM;
8781         }
8782
8783         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8784
8785         *r->out.count = 0;
8786         *r->out.needed = 0;
8787         *r->out.info = NULL;
8788
8789         if (r->in.print_processor_name == NULL ||
8790             !strequal(r->in.print_processor_name, "winprint")) {
8791                 return WERR_UNKNOWN_PRINTPROCESSOR;
8792         }
8793
8794         switch (r->in.level) {
8795         case 1:
8796                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8797                                                         r->out.count);
8798                 break;
8799         default:
8800                 return WERR_UNKNOWN_LEVEL;
8801         }
8802
8803         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8804                                                      spoolss_EnumPrintProcDataTypes,
8805                                                      *r->out.info, r->in.level,
8806                                                      *r->out.count);
8807         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8808         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8809
8810         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8811 }
8812
8813 /****************************************************************************
8814  fill_monitor_1
8815 ****************************************************************************/
8816
8817 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8818                              struct spoolss_MonitorInfo1 *r,
8819                              const char *monitor_name)
8820 {
8821         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8822         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8823
8824         return WERR_OK;
8825 }
8826
8827 /****************************************************************************
8828  fill_monitor_2
8829 ****************************************************************************/
8830
8831 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8832                              struct spoolss_MonitorInfo2 *r,
8833                              const char *monitor_name,
8834                              const char *environment,
8835                              const char *dll_name)
8836 {
8837         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8838         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8839         r->environment                  = talloc_strdup(mem_ctx, environment);
8840         W_ERROR_HAVE_NO_MEMORY(r->environment);
8841         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8842         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8843
8844         return WERR_OK;
8845 }
8846
8847 /****************************************************************************
8848  enumprintmonitors level 1.
8849 ****************************************************************************/
8850
8851 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8852                                         union spoolss_MonitorInfo **info_p,
8853                                         uint32_t *count)
8854 {
8855         union spoolss_MonitorInfo *info;
8856         WERROR result = WERR_OK;
8857
8858         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8859         W_ERROR_HAVE_NO_MEMORY(info);
8860
8861         *count = 2;
8862
8863         result = fill_monitor_1(info, &info[0].info1,
8864                                 SPL_LOCAL_PORT);
8865         if (!W_ERROR_IS_OK(result)) {
8866                 goto out;
8867         }
8868
8869         result = fill_monitor_1(info, &info[1].info1,
8870                                 SPL_TCPIP_PORT);
8871         if (!W_ERROR_IS_OK(result)) {
8872                 goto out;
8873         }
8874
8875 out:
8876         if (!W_ERROR_IS_OK(result)) {
8877                 TALLOC_FREE(info);
8878                 *count = 0;
8879                 return result;
8880         }
8881
8882         *info_p = info;
8883
8884         return WERR_OK;
8885 }
8886
8887 /****************************************************************************
8888  enumprintmonitors level 2.
8889 ****************************************************************************/
8890
8891 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8892                                         union spoolss_MonitorInfo **info_p,
8893                                         uint32_t *count)
8894 {
8895         union spoolss_MonitorInfo *info;
8896         WERROR result = WERR_OK;
8897
8898         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8899         W_ERROR_HAVE_NO_MEMORY(info);
8900
8901         *count = 2;
8902
8903         result = fill_monitor_2(info, &info[0].info2,
8904                                 SPL_LOCAL_PORT,
8905                                 "Windows NT X86", /* FIXME */
8906                                 "localmon.dll");
8907         if (!W_ERROR_IS_OK(result)) {
8908                 goto out;
8909         }
8910
8911         result = fill_monitor_2(info, &info[1].info2,
8912                                 SPL_TCPIP_PORT,
8913                                 "Windows NT X86", /* FIXME */
8914                                 "tcpmon.dll");
8915         if (!W_ERROR_IS_OK(result)) {
8916                 goto out;
8917         }
8918
8919 out:
8920         if (!W_ERROR_IS_OK(result)) {
8921                 TALLOC_FREE(info);
8922                 *count = 0;
8923                 return result;
8924         }
8925
8926         *info_p = info;
8927
8928         return WERR_OK;
8929 }
8930
8931 /****************************************************************
8932  _spoolss_EnumMonitors
8933 ****************************************************************/
8934
8935 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8936                              struct spoolss_EnumMonitors *r)
8937 {
8938         WERROR result;
8939
8940         /* that's an [in out] buffer */
8941
8942         if (!r->in.buffer && (r->in.offered != 0)) {
8943                 return WERR_INVALID_PARAM;
8944         }
8945
8946         DEBUG(5,("_spoolss_EnumMonitors\n"));
8947
8948         /*
8949          * Enumerate the print monitors ...
8950          *
8951          * Just reply with "Local Port", to keep NT happy
8952          * and I can use my nice printer checker.
8953          */
8954
8955         *r->out.count = 0;
8956         *r->out.needed = 0;
8957         *r->out.info = NULL;
8958
8959         switch (r->in.level) {
8960         case 1:
8961                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8962                                                    r->out.count);
8963                 break;
8964         case 2:
8965                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8966                                                    r->out.count);
8967                 break;
8968         default:
8969                 return WERR_UNKNOWN_LEVEL;
8970         }
8971
8972         if (!W_ERROR_IS_OK(result)) {
8973                 return result;
8974         }
8975
8976         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8977                                                      spoolss_EnumMonitors,
8978                                                      *r->out.info, r->in.level,
8979                                                      *r->out.count);
8980         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8981         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8982
8983         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8984 }
8985
8986 /****************************************************************************
8987 ****************************************************************************/
8988
8989 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8990                              const print_queue_struct *queue,
8991                              int count, int snum,
8992                              struct spoolss_PrinterInfo2 *pinfo2,
8993                              uint32_t jobid,
8994                              struct spoolss_JobInfo1 *r)
8995 {
8996         int i = 0;
8997         bool found = false;
8998
8999         for (i=0; i<count; i++) {
9000                 if (queue[i].job == (int)jobid) {
9001                         found = true;
9002                         break;
9003                 }
9004         }
9005
9006         if (found == false) {
9007                 /* NT treats not found as bad param... yet another bad choice */
9008                 return WERR_INVALID_PARAM;
9009         }
9010
9011         return fill_job_info1(mem_ctx,
9012                               r,
9013                               &queue[i],
9014                               i,
9015                               snum,
9016                               pinfo2);
9017 }
9018
9019 /****************************************************************************
9020 ****************************************************************************/
9021
9022 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9023                              const print_queue_struct *queue,
9024                              int count, int snum,
9025                              struct spoolss_PrinterInfo2 *pinfo2,
9026                              uint32_t jobid,
9027                              struct spoolss_JobInfo2 *r)
9028 {
9029         int i = 0;
9030         bool found = false;
9031         struct spoolss_DeviceMode *devmode;
9032         WERROR result;
9033
9034         for (i=0; i<count; i++) {
9035                 if (queue[i].job == (int)jobid) {
9036                         found = true;
9037                         break;
9038                 }
9039         }
9040
9041         if (found == false) {
9042                 /* NT treats not found as bad param... yet another bad
9043                    choice */
9044                 return WERR_INVALID_PARAM;
9045         }
9046
9047         /*
9048          * if the print job does not have a DEVMODE associated with it,
9049          * just use the one for the printer. A NULL devicemode is not
9050          *  a failure condition
9051          */
9052
9053         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9054         if (!devmode) {
9055                 result = spoolss_create_default_devmode(mem_ctx,
9056                                                 pinfo2->printername,
9057                                                 &devmode);
9058                 if (!W_ERROR_IS_OK(result)) {
9059                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9060                         return result;
9061                 }
9062         }
9063
9064         return fill_job_info2(mem_ctx,
9065                               r,
9066                               &queue[i],
9067                               i,
9068                               snum,
9069                               pinfo2,
9070                               devmode);
9071 }
9072
9073 /****************************************************************
9074  _spoolss_GetJob
9075 ****************************************************************/
9076
9077 WERROR _spoolss_GetJob(struct pipes_struct *p,
9078                        struct spoolss_GetJob *r)
9079 {
9080         WERROR result = WERR_OK;
9081         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9082         int snum;
9083         int count;
9084         print_queue_struct      *queue = NULL;
9085         print_status_struct prt_status;
9086
9087         /* that's an [in out] buffer */
9088
9089         if (!r->in.buffer && (r->in.offered != 0)) {
9090                 return WERR_INVALID_PARAM;
9091         }
9092
9093         DEBUG(5,("_spoolss_GetJob\n"));
9094
9095         *r->out.needed = 0;
9096
9097         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9098                 return WERR_BADFID;
9099         }
9100
9101         result = winreg_get_printer(p->mem_ctx,
9102                                     get_session_info_system(),
9103                                     p->msg_ctx,
9104                                     lp_const_servicename(snum),
9105                                     &pinfo2);
9106         if (!W_ERROR_IS_OK(result)) {
9107                 return result;
9108         }
9109
9110         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9111
9112         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9113                      count, prt_status.status, prt_status.message));
9114
9115         switch (r->in.level) {
9116         case 1:
9117                 result = getjob_level_1(p->mem_ctx,
9118                                         queue, count, snum, pinfo2,
9119                                         r->in.job_id, &r->out.info->info1);
9120                 break;
9121         case 2:
9122                 result = getjob_level_2(p->mem_ctx,
9123                                         queue, count, snum, pinfo2,
9124                                         r->in.job_id, &r->out.info->info2);
9125                 break;
9126         default:
9127                 result = WERR_UNKNOWN_LEVEL;
9128                 break;
9129         }
9130
9131         SAFE_FREE(queue);
9132         TALLOC_FREE(pinfo2);
9133
9134         if (!W_ERROR_IS_OK(result)) {
9135                 TALLOC_FREE(r->out.info);
9136                 return result;
9137         }
9138
9139         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9140                                                                                    r->in.level);
9141         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9142
9143         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9144 }
9145
9146 /****************************************************************
9147  _spoolss_GetPrinterDataEx
9148 ****************************************************************/
9149
9150 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9151                                  struct spoolss_GetPrinterDataEx *r)
9152 {
9153
9154         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9155         const char *printer;
9156         int                     snum = 0;
9157         WERROR result = WERR_OK;
9158         DATA_BLOB blob;
9159         enum winreg_Type val_type;
9160         uint8_t *val_data;
9161         uint32_t val_size;
9162
9163
9164         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9165
9166         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9167                 r->in.key_name, r->in.value_name));
9168
9169         /* in case of problem, return some default values */
9170
9171         *r->out.needed  = 0;
9172         *r->out.type    = REG_NONE;
9173
9174         if (!Printer) {
9175                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9176                         OUR_HANDLE(r->in.handle)));
9177                 result = WERR_BADFID;
9178                 goto done;
9179         }
9180
9181         /* Is the handle to a printer or to the server? */
9182
9183         if (Printer->printer_type == SPLHND_SERVER) {
9184
9185                 union spoolss_PrinterData data;
9186
9187                 result = getprinterdata_printer_server(p->mem_ctx,
9188                                                        r->in.value_name,
9189                                                        r->out.type,
9190                                                        &data);
9191                 if (!W_ERROR_IS_OK(result)) {
9192                         return result;
9193                 }
9194
9195                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9196                                                   *r->out.type, &data);
9197                 if (!W_ERROR_IS_OK(result)) {
9198                         return result;
9199                 }
9200
9201                 *r->out.needed = blob.length;
9202
9203                 if (r->in.offered >= *r->out.needed) {
9204                         memcpy(r->out.data, blob.data, blob.length);
9205                 }
9206
9207                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9208         }
9209
9210         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9211                 return WERR_BADFID;
9212         }
9213         printer = lp_const_servicename(snum);
9214
9215         /* check to see if the keyname is valid */
9216         if (!strlen(r->in.key_name)) {
9217                 return WERR_INVALID_PARAM;
9218         }
9219
9220         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9221         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9222             strequal(r->in.value_name, "ChangeId")) {
9223                 *r->out.type = REG_DWORD;
9224                 *r->out.needed = 4;
9225                 if (r->in.offered >= *r->out.needed) {
9226                         uint32_t changeid = 0;
9227
9228                         result = winreg_printer_get_changeid(p->mem_ctx,
9229                                                              get_session_info_system(),
9230                                                              p->msg_ctx,
9231                                                              printer,
9232                                                              &changeid);
9233                         if (!W_ERROR_IS_OK(result)) {
9234                                 return result;
9235                         }
9236
9237                         SIVAL(r->out.data, 0, changeid);
9238                         result = WERR_OK;
9239                 }
9240                 goto done;
9241         }
9242
9243         result = winreg_get_printer_dataex(p->mem_ctx,
9244                                            get_session_info_system(),
9245                                            p->msg_ctx,
9246                                            printer,
9247                                            r->in.key_name,
9248                                            r->in.value_name,
9249                                            &val_type,
9250                                            &val_data,
9251                                            &val_size);
9252         if (!W_ERROR_IS_OK(result)) {
9253                 return result;
9254         }
9255
9256         *r->out.needed = val_size;
9257         *r->out.type = val_type;
9258
9259         if (r->in.offered >= *r->out.needed) {
9260                 memcpy(r->out.data, val_data, val_size);
9261         }
9262
9263  done:
9264         /* retain type when returning WERR_MORE_DATA */
9265         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9266
9267         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9268 }
9269
9270 /****************************************************************
9271  _spoolss_SetPrinterDataEx
9272 ****************************************************************/
9273
9274 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9275                                  struct spoolss_SetPrinterDataEx *r)
9276 {
9277         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9278         int                     snum = 0;
9279         WERROR                  result = WERR_OK;
9280         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9281         char                    *oid_string;
9282
9283         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9284
9285         /* From MSDN documentation of SetPrinterDataEx: pass request to
9286            SetPrinterData if key is "PrinterDriverData" */
9287
9288         if (!Printer) {
9289                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9290                         OUR_HANDLE(r->in.handle)));
9291                 return WERR_BADFID;
9292         }
9293
9294         if (Printer->printer_type == SPLHND_SERVER) {
9295                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9296                         "Not implemented for server handles yet\n"));
9297                 return WERR_INVALID_PARAM;
9298         }
9299
9300         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9301                 return WERR_BADFID;
9302         }
9303
9304         /*
9305          * Access check : NT returns "access denied" if you make a
9306          * SetPrinterData call without the necessary privildge.
9307          * we were originally returning OK if nothing changed
9308          * which made Win2k issue **a lot** of SetPrinterData
9309          * when connecting to a printer  --jerry
9310          */
9311
9312         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9313                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9314                         "change denied by handle access permissions\n"));
9315                 return WERR_ACCESS_DENIED;
9316         }
9317
9318         result = winreg_get_printer(Printer,
9319                                     get_session_info_system(),
9320                                     p->msg_ctx,
9321                                     lp_servicename(snum),
9322                                     &pinfo2);
9323         if (!W_ERROR_IS_OK(result)) {
9324                 return result;
9325         }
9326
9327         /* check for OID in valuename */
9328
9329         oid_string = strchr(r->in.value_name, ',');
9330         if (oid_string) {
9331                 *oid_string = '\0';
9332                 oid_string++;
9333         }
9334
9335         /* save the registry data */
9336
9337         result = winreg_set_printer_dataex(p->mem_ctx,
9338                                            get_session_info_system(),
9339                                            p->msg_ctx,
9340                                            pinfo2->sharename,
9341                                            r->in.key_name,
9342                                            r->in.value_name,
9343                                            r->in.type,
9344                                            r->in.data,
9345                                            r->in.offered);
9346
9347         if (W_ERROR_IS_OK(result)) {
9348                 /* save the OID if one was specified */
9349                 if (oid_string) {
9350                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9351                                 r->in.key_name, SPOOL_OID_KEY);
9352                         if (!str) {
9353                                 result = WERR_NOMEM;
9354                                 goto done;
9355                         }
9356
9357                         /*
9358                          * I'm not checking the status here on purpose.  Don't know
9359                          * if this is right, but I'm returning the status from the
9360                          * previous set_printer_dataex() call.  I have no idea if
9361                          * this is right.    --jerry
9362                          */
9363                         winreg_set_printer_dataex(p->mem_ctx,
9364                                                   get_session_info_system(),
9365                                                   p->msg_ctx,
9366                                                   pinfo2->sharename,
9367                                                   str,
9368                                                   r->in.value_name,
9369                                                   REG_SZ,
9370                                                   (uint8_t *) oid_string,
9371                                                   strlen(oid_string) + 1);
9372                 }
9373
9374                 result = winreg_printer_update_changeid(p->mem_ctx,
9375                                                         get_session_info_system(),
9376                                                         p->msg_ctx,
9377                                                         lp_const_servicename(snum));
9378
9379         }
9380
9381 done:
9382         talloc_free(pinfo2);
9383         return result;
9384 }
9385
9386 /****************************************************************
9387  _spoolss_DeletePrinterDataEx
9388 ****************************************************************/
9389
9390 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9391                                     struct spoolss_DeletePrinterDataEx *r)
9392 {
9393         const char *printer;
9394         int             snum=0;
9395         WERROR          status = WERR_OK;
9396         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9397
9398         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9399
9400         if (!Printer) {
9401                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9402                         "Invalid handle (%s:%u:%u).\n",
9403                         OUR_HANDLE(r->in.handle)));
9404                 return WERR_BADFID;
9405         }
9406
9407         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9408                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9409                         "printer properties change denied by handle\n"));
9410                 return WERR_ACCESS_DENIED;
9411         }
9412
9413         if (!r->in.value_name || !r->in.key_name) {
9414                 return WERR_NOMEM;
9415         }
9416
9417         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9418                 return WERR_BADFID;
9419         }
9420         printer = lp_const_servicename(snum);
9421
9422         status = winreg_delete_printer_dataex(p->mem_ctx,
9423                                               get_session_info_system(),
9424                                               p->msg_ctx,
9425                                               printer,
9426                                               r->in.key_name,
9427                                               r->in.value_name);
9428         if (W_ERROR_IS_OK(status)) {
9429                 status = winreg_printer_update_changeid(p->mem_ctx,
9430                                                         get_session_info_system(),
9431                                                         p->msg_ctx,
9432                                                         printer);
9433         }
9434
9435         return status;
9436 }
9437
9438 /****************************************************************
9439  _spoolss_EnumPrinterKey
9440 ****************************************************************/
9441
9442 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9443                                struct spoolss_EnumPrinterKey *r)
9444 {
9445         uint32_t        num_keys;
9446         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9447         int             snum = 0;
9448         WERROR          result = WERR_BADFILE;
9449         const char **array = NULL;
9450         DATA_BLOB blob;
9451
9452         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9453
9454         if (!Printer) {
9455                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9456                         OUR_HANDLE(r->in.handle)));
9457                 return WERR_BADFID;
9458         }
9459
9460         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9461                 return WERR_BADFID;
9462         }
9463
9464         result = winreg_enum_printer_key(p->mem_ctx,
9465                                          get_session_info_system(),
9466                                          p->msg_ctx,
9467                                          lp_const_servicename(snum),
9468                                          r->in.key_name,
9469                                          &num_keys,
9470                                          &array);
9471         if (!W_ERROR_IS_OK(result)) {
9472                 goto done;
9473         }
9474
9475         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9476                 result = WERR_NOMEM;
9477                 goto done;
9478         }
9479
9480         *r->out._ndr_size = r->in.offered / 2;
9481         *r->out.needed = blob.length;
9482
9483         if (r->in.offered < *r->out.needed) {
9484                 result = WERR_MORE_DATA;
9485         } else {
9486                 result = WERR_OK;
9487                 r->out.key_buffer->string_array = array;
9488         }
9489
9490  done:
9491         if (!W_ERROR_IS_OK(result)) {
9492                 TALLOC_FREE(array);
9493                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9494                         *r->out.needed = 0;
9495                 }
9496         }
9497
9498         return result;
9499 }
9500
9501 /****************************************************************
9502  _spoolss_DeletePrinterKey
9503 ****************************************************************/
9504
9505 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9506                                  struct spoolss_DeletePrinterKey *r)
9507 {
9508         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9509         int                     snum=0;
9510         WERROR                  status;
9511         const char *printer;
9512
9513         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9514
9515         if (!Printer) {
9516                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9517                         OUR_HANDLE(r->in.handle)));
9518                 return WERR_BADFID;
9519         }
9520
9521         /* if keyname == NULL, return error */
9522         if ( !r->in.key_name )
9523                 return WERR_INVALID_PARAM;
9524
9525         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9526                 return WERR_BADFID;
9527         }
9528
9529         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9530                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9531                         "printer properties change denied by handle\n"));
9532                 return WERR_ACCESS_DENIED;
9533         }
9534
9535         printer = lp_const_servicename(snum);
9536
9537         /* delete the key and all subkeys */
9538         status = winreg_delete_printer_key(p->mem_ctx,
9539                                            get_session_info_system(),
9540                                            p->msg_ctx,
9541                                            printer,
9542                                            r->in.key_name);
9543         if (W_ERROR_IS_OK(status)) {
9544                 status = winreg_printer_update_changeid(p->mem_ctx,
9545                                                         get_session_info_system(),
9546                                                         p->msg_ctx,
9547                                                         printer);
9548         }
9549
9550         return status;
9551 }
9552
9553 /****************************************************************
9554  _spoolss_EnumPrinterDataEx
9555 ****************************************************************/
9556
9557 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9558                                   struct spoolss_EnumPrinterDataEx *r)
9559 {
9560         uint32_t        count = 0;
9561         struct spoolss_PrinterEnumValues *info = NULL;
9562         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9563         int             snum;
9564         WERROR          result;
9565
9566         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9567
9568         *r->out.count = 0;
9569         *r->out.needed = 0;
9570         *r->out.info = NULL;
9571
9572         if (!Printer) {
9573                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9574                         OUR_HANDLE(r->in.handle)));
9575                 return WERR_BADFID;
9576         }
9577
9578         /*
9579          * first check for a keyname of NULL or "".  Win2k seems to send
9580          * this a lot and we should send back WERR_INVALID_PARAM
9581          * no need to spend time looking up the printer in this case.
9582          * --jerry
9583          */
9584
9585         if (!strlen(r->in.key_name)) {
9586                 result = WERR_INVALID_PARAM;
9587                 goto done;
9588         }
9589
9590         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9591                 return WERR_BADFID;
9592         }
9593
9594         /* now look for a match on the key name */
9595         result = winreg_enum_printer_dataex(p->mem_ctx,
9596                                             get_session_info_system(),
9597                                             p->msg_ctx,
9598                                             lp_const_servicename(snum),
9599                                             r->in.key_name,
9600                                             &count,
9601                                             &info);
9602         if (!W_ERROR_IS_OK(result)) {
9603                 goto done;
9604         }
9605
9606 #if 0 /* FIXME - gd */
9607         /* housekeeping information in the reply */
9608
9609         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9610          * the hand marshalled container size is a multiple
9611          * of 4 bytes for RPC alignment.
9612          */
9613
9614         if (needed % 4) {
9615                 needed += 4-(needed % 4);
9616         }
9617 #endif
9618         *r->out.count   = count;
9619         *r->out.info    = info;
9620
9621  done:
9622         if (!W_ERROR_IS_OK(result)) {
9623                 return result;
9624         }
9625
9626         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9627                                                spoolss_EnumPrinterDataEx,
9628                                                *r->out.info,
9629                                                *r->out.count);
9630         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9631         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9632
9633         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9634 }
9635
9636 /****************************************************************************
9637 ****************************************************************************/
9638
9639 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9640                                                  const char *servername,
9641                                                  const char *environment,
9642                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9643 {
9644         WERROR werr;
9645         char *path = NULL;
9646
9647         werr = compose_spoolss_server_path(mem_ctx,
9648                                            servername,
9649                                            environment,
9650                                            SPOOLSS_PRTPROCS_PATH,
9651                                            &path);
9652         if (!W_ERROR_IS_OK(werr)) {
9653                 return werr;
9654         }
9655
9656         DEBUG(4,("print processor directory: [%s]\n", path));
9657
9658         r->directory_name = path;
9659
9660         return WERR_OK;
9661 }
9662
9663 /****************************************************************
9664  _spoolss_GetPrintProcessorDirectory
9665 ****************************************************************/
9666
9667 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9668                                            struct spoolss_GetPrintProcessorDirectory *r)
9669 {
9670         WERROR result;
9671         char *prnproc_share = NULL;
9672         bool prnproc_share_exists = false;
9673         int snum;
9674
9675         /* that's an [in out] buffer */
9676
9677         if (!r->in.buffer && (r->in.offered != 0)) {
9678                 return WERR_INVALID_PARAM;
9679         }
9680
9681         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9682                 r->in.level));
9683
9684         *r->out.needed = 0;
9685
9686         /* r->in.level is ignored */
9687
9688         /* We always should reply with a local print processor directory so that
9689          * users are not forced to have a [prnproc$] share on the Samba spoolss
9690          * server, if users decide to do so, lets announce it though - Guenther */
9691
9692         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9693         if (!prnproc_share) {
9694                 return WERR_NOMEM;
9695         }
9696         if (snum != -1) {
9697                 prnproc_share_exists = true;
9698         }
9699
9700         result = getprintprocessordirectory_level_1(p->mem_ctx,
9701                                                     prnproc_share_exists ? r->in.server : NULL,
9702                                                     r->in.environment,
9703                                                     &r->out.info->info1);
9704         if (!W_ERROR_IS_OK(result)) {
9705                 TALLOC_FREE(r->out.info);
9706                 return result;
9707         }
9708
9709         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9710                                                                                    r->out.info, r->in.level);
9711         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9712
9713         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9714 }
9715
9716 /*******************************************************************
9717  ********************************************************************/
9718
9719 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9720                                const char *dllname)
9721 {
9722         enum ndr_err_code ndr_err;
9723         struct spoolss_MonitorUi ui;
9724
9725         ui.dll_name = dllname;
9726
9727         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9728                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9729         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9730                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9731         }
9732         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9733 }
9734
9735 /*******************************************************************
9736  Streams the monitor UI DLL name in UNICODE
9737 *******************************************************************/
9738
9739 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9740                                struct security_token *token, DATA_BLOB *in,
9741                                DATA_BLOB *out, uint32_t *needed)
9742 {
9743         const char *dllname = "tcpmonui.dll";
9744
9745         *needed = (strlen(dllname)+1) * 2;
9746
9747         if (out->length < *needed) {
9748                 return WERR_INSUFFICIENT_BUFFER;
9749         }
9750
9751         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9752                 return WERR_NOMEM;
9753         }
9754
9755         return WERR_OK;
9756 }
9757
9758 /*******************************************************************
9759  ********************************************************************/
9760
9761 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9762                              struct spoolss_PortData1 *port1,
9763                              const DATA_BLOB *buf)
9764 {
9765         enum ndr_err_code ndr_err;
9766         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9767                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9768         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9769                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9770         }
9771         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9772 }
9773
9774 /*******************************************************************
9775  ********************************************************************/
9776
9777 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9778                              struct spoolss_PortData2 *port2,
9779                              const DATA_BLOB *buf)
9780 {
9781         enum ndr_err_code ndr_err;
9782         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9783                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9784         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9785                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9786         }
9787         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9788 }
9789
9790 /*******************************************************************
9791  Create a new TCP/IP port
9792 *******************************************************************/
9793
9794 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9795                              struct security_token *token, DATA_BLOB *in,
9796                              DATA_BLOB *out, uint32_t *needed)
9797 {
9798         struct spoolss_PortData1 port1;
9799         struct spoolss_PortData2 port2;
9800         char *device_uri = NULL;
9801         uint32_t version;
9802
9803         const char *portname;
9804         const char *hostaddress;
9805         const char *queue;
9806         uint32_t port_number;
9807         uint32_t protocol;
9808
9809         /* peek for spoolss_PortData version */
9810
9811         if (!in || (in->length < (128 + 4))) {
9812                 return WERR_GENERAL_FAILURE;
9813         }
9814
9815         version = IVAL(in->data, 128);
9816
9817         switch (version) {
9818                 case 1:
9819                         ZERO_STRUCT(port1);
9820
9821                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9822                                 return WERR_NOMEM;
9823                         }
9824
9825                         portname        = port1.portname;
9826                         hostaddress     = port1.hostaddress;
9827                         queue           = port1.queue;
9828                         protocol        = port1.protocol;
9829                         port_number     = port1.port_number;
9830
9831                         break;
9832                 case 2:
9833                         ZERO_STRUCT(port2);
9834
9835                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9836                                 return WERR_NOMEM;
9837                         }
9838
9839                         portname        = port2.portname;
9840                         hostaddress     = port2.hostaddress;
9841                         queue           = port2.queue;
9842                         protocol        = port2.protocol;
9843                         port_number     = port2.port_number;
9844
9845                         break;
9846                 default:
9847                         DEBUG(1,("xcvtcp_addport: "
9848                                 "unknown version of port_data: %d\n", version));
9849                         return WERR_UNKNOWN_PORT;
9850         }
9851
9852         /* create the device URI and call the add_port_hook() */
9853
9854         switch (protocol) {
9855         case PROTOCOL_RAWTCP_TYPE:
9856                 device_uri = talloc_asprintf(mem_ctx,
9857                                 "socket://%s:%d/", hostaddress,
9858                                 port_number);
9859                 break;
9860
9861         case PROTOCOL_LPR_TYPE:
9862                 device_uri = talloc_asprintf(mem_ctx,
9863                         "lpr://%s/%s", hostaddress, queue );
9864                 break;
9865
9866         default:
9867                 return WERR_UNKNOWN_PORT;
9868         }
9869
9870         if (!device_uri) {
9871                 return WERR_NOMEM;
9872         }
9873
9874         return add_port_hook(mem_ctx, token, portname, device_uri);
9875 }
9876
9877 /*******************************************************************
9878 *******************************************************************/
9879
9880 struct xcv_api_table xcvtcp_cmds[] = {
9881         { "MonitorUI",  xcvtcp_monitorui },
9882         { "AddPort",    xcvtcp_addport},
9883         { NULL,         NULL }
9884 };
9885
9886 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9887                                      struct security_token *token, const char *command,
9888                                      DATA_BLOB *inbuf,
9889                                      DATA_BLOB *outbuf,
9890                                      uint32_t *needed )
9891 {
9892         int i;
9893
9894         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9895
9896         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9897                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9898                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9899         }
9900
9901         return WERR_BADFUNC;
9902 }
9903
9904 /*******************************************************************
9905 *******************************************************************/
9906 #if 0   /* don't support management using the "Local Port" monitor */
9907
9908 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9909                                  struct security_token *token, DATA_BLOB *in,
9910                                  DATA_BLOB *out, uint32_t *needed)
9911 {
9912         const char *dllname = "localui.dll";
9913
9914         *needed = (strlen(dllname)+1) * 2;
9915
9916         if (out->length < *needed) {
9917                 return WERR_INSUFFICIENT_BUFFER;
9918         }
9919
9920         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9921                 return WERR_NOMEM;
9922         }
9923
9924         return WERR_OK;
9925 }
9926
9927 /*******************************************************************
9928 *******************************************************************/
9929
9930 struct xcv_api_table xcvlocal_cmds[] = {
9931         { "MonitorUI",  xcvlocal_monitorui },
9932         { NULL,         NULL }
9933 };
9934 #else
9935 struct xcv_api_table xcvlocal_cmds[] = {
9936         { NULL,         NULL }
9937 };
9938 #endif
9939
9940
9941
9942 /*******************************************************************
9943 *******************************************************************/
9944
9945 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9946                                        struct security_token *token, const char *command,
9947                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9948                                        uint32_t *needed)
9949 {
9950         int i;
9951
9952         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9953
9954         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9955                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9956                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9957         }
9958         return WERR_BADFUNC;
9959 }
9960
9961 /****************************************************************
9962  _spoolss_XcvData
9963 ****************************************************************/
9964
9965 WERROR _spoolss_XcvData(struct pipes_struct *p,
9966                         struct spoolss_XcvData *r)
9967 {
9968         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9969         DATA_BLOB out_data = data_blob_null;
9970         WERROR werror;
9971
9972         if (!Printer) {
9973                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9974                         OUR_HANDLE(r->in.handle)));
9975                 return WERR_BADFID;
9976         }
9977
9978         /* Has to be a handle to the TCP/IP port monitor */
9979
9980         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9981                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9982                 return WERR_BADFID;
9983         }
9984
9985         /* requires administrative access to the server */
9986
9987         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9988                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9989                 return WERR_ACCESS_DENIED;
9990         }
9991
9992         /* Allocate the outgoing buffer */
9993
9994         if (r->in.out_data_size) {
9995                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9996                 if (out_data.data == NULL) {
9997                         return WERR_NOMEM;
9998                 }
9999         }
10000
10001         switch ( Printer->printer_type ) {
10002         case SPLHND_PORTMON_TCP:
10003                 werror = process_xcvtcp_command(p->mem_ctx,
10004                                                 p->session_info->security_token,
10005                                                 r->in.function_name,
10006                                                 &r->in.in_data, &out_data,
10007                                                 r->out.needed);
10008                 break;
10009         case SPLHND_PORTMON_LOCAL:
10010                 werror = process_xcvlocal_command(p->mem_ctx,
10011                                                   p->session_info->security_token,
10012                                                   r->in.function_name,
10013                                                   &r->in.in_data, &out_data,
10014                                                   r->out.needed);
10015                 break;
10016         default:
10017                 werror = WERR_INVALID_PRINT_MONITOR;
10018         }
10019
10020         if (!W_ERROR_IS_OK(werror)) {
10021                 return werror;
10022         }
10023
10024         *r->out.status_code = 0;
10025
10026         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10027                 memcpy(r->out.out_data, out_data.data,
10028                         MIN(r->in.out_data_size, out_data.length));
10029         }
10030
10031         return WERR_OK;
10032 }
10033
10034 /****************************************************************
10035  _spoolss_AddPrintProcessor
10036 ****************************************************************/
10037
10038 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10039                                   struct spoolss_AddPrintProcessor *r)
10040 {
10041         /* for now, just indicate success and ignore the add.  We'll
10042            automatically set the winprint processor for printer
10043            entries later.  Used to debug the LexMark Optra S 1855 PCL
10044            driver --jerry */
10045
10046         return WERR_OK;
10047 }
10048
10049 /****************************************************************
10050  _spoolss_AddPort
10051 ****************************************************************/
10052
10053 WERROR _spoolss_AddPort(struct pipes_struct *p,
10054                         struct spoolss_AddPort *r)
10055 {
10056         /* do what w2k3 does */
10057
10058         return WERR_NOT_SUPPORTED;
10059 }
10060
10061 /****************************************************************
10062  _spoolss_GetPrinterDriver
10063 ****************************************************************/
10064
10065 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10066                                  struct spoolss_GetPrinterDriver *r)
10067 {
10068         p->rng_fault_state = true;
10069         return WERR_NOT_SUPPORTED;
10070 }
10071
10072 /****************************************************************
10073  _spoolss_ReadPrinter
10074 ****************************************************************/
10075
10076 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10077                             struct spoolss_ReadPrinter *r)
10078 {
10079         p->rng_fault_state = true;
10080         return WERR_NOT_SUPPORTED;
10081 }
10082
10083 /****************************************************************
10084  _spoolss_WaitForPrinterChange
10085 ****************************************************************/
10086
10087 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10088                                      struct spoolss_WaitForPrinterChange *r)
10089 {
10090         p->rng_fault_state = true;
10091         return WERR_NOT_SUPPORTED;
10092 }
10093
10094 /****************************************************************
10095  _spoolss_ConfigurePort
10096 ****************************************************************/
10097
10098 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10099                               struct spoolss_ConfigurePort *r)
10100 {
10101         p->rng_fault_state = true;
10102         return WERR_NOT_SUPPORTED;
10103 }
10104
10105 /****************************************************************
10106  _spoolss_DeletePort
10107 ****************************************************************/
10108
10109 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10110                            struct spoolss_DeletePort *r)
10111 {
10112         p->rng_fault_state = true;
10113         return WERR_NOT_SUPPORTED;
10114 }
10115
10116 /****************************************************************
10117  _spoolss_CreatePrinterIC
10118 ****************************************************************/
10119
10120 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10121                                 struct spoolss_CreatePrinterIC *r)
10122 {
10123         p->rng_fault_state = true;
10124         return WERR_NOT_SUPPORTED;
10125 }
10126
10127 /****************************************************************
10128  _spoolss_PlayGDIScriptOnPrinterIC
10129 ****************************************************************/
10130
10131 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10132                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10133 {
10134         p->rng_fault_state = true;
10135         return WERR_NOT_SUPPORTED;
10136 }
10137
10138 /****************************************************************
10139  _spoolss_DeletePrinterIC
10140 ****************************************************************/
10141
10142 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10143                                 struct spoolss_DeletePrinterIC *r)
10144 {
10145         p->rng_fault_state = true;
10146         return WERR_NOT_SUPPORTED;
10147 }
10148
10149 /****************************************************************
10150  _spoolss_AddPrinterConnection
10151 ****************************************************************/
10152
10153 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10154                                      struct spoolss_AddPrinterConnection *r)
10155 {
10156         p->rng_fault_state = true;
10157         return WERR_NOT_SUPPORTED;
10158 }
10159
10160 /****************************************************************
10161  _spoolss_DeletePrinterConnection
10162 ****************************************************************/
10163
10164 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10165                                         struct spoolss_DeletePrinterConnection *r)
10166 {
10167         p->rng_fault_state = true;
10168         return WERR_NOT_SUPPORTED;
10169 }
10170
10171 /****************************************************************
10172  _spoolss_PrinterMessageBox
10173 ****************************************************************/
10174
10175 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10176                                   struct spoolss_PrinterMessageBox *r)
10177 {
10178         p->rng_fault_state = true;
10179         return WERR_NOT_SUPPORTED;
10180 }
10181
10182 /****************************************************************
10183  _spoolss_AddMonitor
10184 ****************************************************************/
10185
10186 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10187                            struct spoolss_AddMonitor *r)
10188 {
10189         p->rng_fault_state = true;
10190         return WERR_NOT_SUPPORTED;
10191 }
10192
10193 /****************************************************************
10194  _spoolss_DeleteMonitor
10195 ****************************************************************/
10196
10197 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10198                               struct spoolss_DeleteMonitor *r)
10199 {
10200         p->rng_fault_state = true;
10201         return WERR_NOT_SUPPORTED;
10202 }
10203
10204 /****************************************************************
10205  _spoolss_DeletePrintProcessor
10206 ****************************************************************/
10207
10208 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10209                                      struct spoolss_DeletePrintProcessor *r)
10210 {
10211         p->rng_fault_state = true;
10212         return WERR_NOT_SUPPORTED;
10213 }
10214
10215 /****************************************************************
10216  _spoolss_AddPrintProvidor
10217 ****************************************************************/
10218
10219 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10220                                  struct spoolss_AddPrintProvidor *r)
10221 {
10222         p->rng_fault_state = true;
10223         return WERR_NOT_SUPPORTED;
10224 }
10225
10226 /****************************************************************
10227  _spoolss_DeletePrintProvidor
10228 ****************************************************************/
10229
10230 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10231                                     struct spoolss_DeletePrintProvidor *r)
10232 {
10233         p->rng_fault_state = true;
10234         return WERR_NOT_SUPPORTED;
10235 }
10236
10237 /****************************************************************
10238  _spoolss_FindFirstPrinterChangeNotification
10239 ****************************************************************/
10240
10241 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10242                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10243 {
10244         p->rng_fault_state = true;
10245         return WERR_NOT_SUPPORTED;
10246 }
10247
10248 /****************************************************************
10249  _spoolss_FindNextPrinterChangeNotification
10250 ****************************************************************/
10251
10252 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10253                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10254 {
10255         p->rng_fault_state = true;
10256         return WERR_NOT_SUPPORTED;
10257 }
10258
10259 /****************************************************************
10260  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10261 ****************************************************************/
10262
10263 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10264                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10265 {
10266         p->rng_fault_state = true;
10267         return WERR_NOT_SUPPORTED;
10268 }
10269
10270 /****************************************************************
10271  _spoolss_ReplyOpenPrinter
10272 ****************************************************************/
10273
10274 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10275                                  struct spoolss_ReplyOpenPrinter *r)
10276 {
10277         p->rng_fault_state = true;
10278         return WERR_NOT_SUPPORTED;
10279 }
10280
10281 /****************************************************************
10282  _spoolss_RouterReplyPrinter
10283 ****************************************************************/
10284
10285 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10286                                    struct spoolss_RouterReplyPrinter *r)
10287 {
10288         p->rng_fault_state = true;
10289         return WERR_NOT_SUPPORTED;
10290 }
10291
10292 /****************************************************************
10293  _spoolss_ReplyClosePrinter
10294 ****************************************************************/
10295
10296 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10297                                   struct spoolss_ReplyClosePrinter *r)
10298 {
10299         p->rng_fault_state = true;
10300         return WERR_NOT_SUPPORTED;
10301 }
10302
10303 /****************************************************************
10304  _spoolss_AddPortEx
10305 ****************************************************************/
10306
10307 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10308                           struct spoolss_AddPortEx *r)
10309 {
10310         p->rng_fault_state = true;
10311         return WERR_NOT_SUPPORTED;
10312 }
10313
10314 /****************************************************************
10315  _spoolss_RouterFindFirstPrinterChangeNotification
10316 ****************************************************************/
10317
10318 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10319                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10320 {
10321         p->rng_fault_state = true;
10322         return WERR_NOT_SUPPORTED;
10323 }
10324
10325 /****************************************************************
10326  _spoolss_SpoolerInit
10327 ****************************************************************/
10328
10329 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10330                             struct spoolss_SpoolerInit *r)
10331 {
10332         p->rng_fault_state = true;
10333         return WERR_NOT_SUPPORTED;
10334 }
10335
10336 /****************************************************************
10337  _spoolss_ResetPrinterEx
10338 ****************************************************************/
10339
10340 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10341                                struct spoolss_ResetPrinterEx *r)
10342 {
10343         p->rng_fault_state = true;
10344         return WERR_NOT_SUPPORTED;
10345 }
10346
10347 /****************************************************************
10348  _spoolss_RouterReplyPrinterEx
10349 ****************************************************************/
10350
10351 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10352                                      struct spoolss_RouterReplyPrinterEx *r)
10353 {
10354         p->rng_fault_state = true;
10355         return WERR_NOT_SUPPORTED;
10356 }
10357
10358 /****************************************************************
10359  _spoolss_44
10360 ****************************************************************/
10361
10362 WERROR _spoolss_44(struct pipes_struct *p,
10363                    struct spoolss_44 *r)
10364 {
10365         p->rng_fault_state = true;
10366         return WERR_NOT_SUPPORTED;
10367 }
10368
10369 /****************************************************************
10370  _spoolss_SetPort
10371 ****************************************************************/
10372
10373 WERROR _spoolss_SetPort(struct pipes_struct *p,
10374                         struct spoolss_SetPort *r)
10375 {
10376         p->rng_fault_state = true;
10377         return WERR_NOT_SUPPORTED;
10378 }
10379
10380 /****************************************************************
10381  _spoolss_4a
10382 ****************************************************************/
10383
10384 WERROR _spoolss_4a(struct pipes_struct *p,
10385                    struct spoolss_4a *r)
10386 {
10387         p->rng_fault_state = true;
10388         return WERR_NOT_SUPPORTED;
10389 }
10390
10391 /****************************************************************
10392  _spoolss_4b
10393 ****************************************************************/
10394
10395 WERROR _spoolss_4b(struct pipes_struct *p,
10396                    struct spoolss_4b *r)
10397 {
10398         p->rng_fault_state = true;
10399         return WERR_NOT_SUPPORTED;
10400 }
10401
10402 /****************************************************************
10403  _spoolss_4c
10404 ****************************************************************/
10405
10406 WERROR _spoolss_4c(struct pipes_struct *p,
10407                    struct spoolss_4c *r)
10408 {
10409         p->rng_fault_state = true;
10410         return WERR_NOT_SUPPORTED;
10411 }
10412
10413 /****************************************************************
10414  _spoolss_53
10415 ****************************************************************/
10416
10417 WERROR _spoolss_53(struct pipes_struct *p,
10418                    struct spoolss_53 *r)
10419 {
10420         p->rng_fault_state = true;
10421         return WERR_NOT_SUPPORTED;
10422 }
10423
10424 /****************************************************************
10425  _spoolss_AddPerMachineConnection
10426 ****************************************************************/
10427
10428 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10429                                         struct spoolss_AddPerMachineConnection *r)
10430 {
10431         p->rng_fault_state = true;
10432         return WERR_NOT_SUPPORTED;
10433 }
10434
10435 /****************************************************************
10436  _spoolss_DeletePerMachineConnection
10437 ****************************************************************/
10438
10439 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10440                                            struct spoolss_DeletePerMachineConnection *r)
10441 {
10442         p->rng_fault_state = true;
10443         return WERR_NOT_SUPPORTED;
10444 }
10445
10446 /****************************************************************
10447  _spoolss_EnumPerMachineConnections
10448 ****************************************************************/
10449
10450 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10451                                           struct spoolss_EnumPerMachineConnections *r)
10452 {
10453         p->rng_fault_state = true;
10454         return WERR_NOT_SUPPORTED;
10455 }
10456
10457 /****************************************************************
10458  _spoolss_5a
10459 ****************************************************************/
10460
10461 WERROR _spoolss_5a(struct pipes_struct *p,
10462                    struct spoolss_5a *r)
10463 {
10464         p->rng_fault_state = true;
10465         return WERR_NOT_SUPPORTED;
10466 }
10467
10468 /****************************************************************
10469  _spoolss_5b
10470 ****************************************************************/
10471
10472 WERROR _spoolss_5b(struct pipes_struct *p,
10473                    struct spoolss_5b *r)
10474 {
10475         p->rng_fault_state = true;
10476         return WERR_NOT_SUPPORTED;
10477 }
10478
10479 /****************************************************************
10480  _spoolss_5c
10481 ****************************************************************/
10482
10483 WERROR _spoolss_5c(struct pipes_struct *p,
10484                    struct spoolss_5c *r)
10485 {
10486         p->rng_fault_state = true;
10487         return WERR_NOT_SUPPORTED;
10488 }
10489
10490 /****************************************************************
10491  _spoolss_5d
10492 ****************************************************************/
10493
10494 WERROR _spoolss_5d(struct pipes_struct *p,
10495                    struct spoolss_5d *r)
10496 {
10497         p->rng_fault_state = true;
10498         return WERR_NOT_SUPPORTED;
10499 }
10500
10501 /****************************************************************
10502  _spoolss_5e
10503 ****************************************************************/
10504
10505 WERROR _spoolss_5e(struct pipes_struct *p,
10506                    struct spoolss_5e *r)
10507 {
10508         p->rng_fault_state = true;
10509         return WERR_NOT_SUPPORTED;
10510 }
10511
10512 /****************************************************************
10513  _spoolss_5f
10514 ****************************************************************/
10515
10516 WERROR _spoolss_5f(struct pipes_struct *p,
10517                    struct spoolss_5f *r)
10518 {
10519         p->rng_fault_state = true;
10520         return WERR_NOT_SUPPORTED;
10521 }
10522
10523 /****************************************************************
10524  _spoolss_60
10525 ****************************************************************/
10526
10527 WERROR _spoolss_60(struct pipes_struct *p,
10528                    struct spoolss_60 *r)
10529 {
10530         p->rng_fault_state = true;
10531         return WERR_NOT_SUPPORTED;
10532 }
10533
10534 /****************************************************************
10535  _spoolss_61
10536 ****************************************************************/
10537
10538 WERROR _spoolss_61(struct pipes_struct *p,
10539                    struct spoolss_61 *r)
10540 {
10541         p->rng_fault_state = true;
10542         return WERR_NOT_SUPPORTED;
10543 }
10544
10545 /****************************************************************
10546  _spoolss_62
10547 ****************************************************************/
10548
10549 WERROR _spoolss_62(struct pipes_struct *p,
10550                    struct spoolss_62 *r)
10551 {
10552         p->rng_fault_state = true;
10553         return WERR_NOT_SUPPORTED;
10554 }
10555
10556 /****************************************************************
10557  _spoolss_63
10558 ****************************************************************/
10559
10560 WERROR _spoolss_63(struct pipes_struct *p,
10561                    struct spoolss_63 *r)
10562 {
10563         p->rng_fault_state = true;
10564         return WERR_NOT_SUPPORTED;
10565 }
10566
10567 /****************************************************************
10568  _spoolss_64
10569 ****************************************************************/
10570
10571 WERROR _spoolss_64(struct pipes_struct *p,
10572                    struct spoolss_64 *r)
10573 {
10574         p->rng_fault_state = true;
10575         return WERR_NOT_SUPPORTED;
10576 }
10577
10578 /****************************************************************
10579  _spoolss_65
10580 ****************************************************************/
10581
10582 WERROR _spoolss_65(struct pipes_struct *p,
10583                    struct spoolss_65 *r)
10584 {
10585         p->rng_fault_state = true;
10586         return WERR_NOT_SUPPORTED;
10587 }
10588
10589 /****************************************************************
10590  _spoolss_GetCorePrinterDrivers
10591 ****************************************************************/
10592
10593 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10594                                       struct spoolss_GetCorePrinterDrivers *r)
10595 {
10596         p->rng_fault_state = true;
10597         return WERR_NOT_SUPPORTED;
10598 }
10599
10600 /****************************************************************
10601  _spoolss_67
10602 ****************************************************************/
10603
10604 WERROR _spoolss_67(struct pipes_struct *p,
10605                    struct spoolss_67 *r)
10606 {
10607         p->rng_fault_state = true;
10608         return WERR_NOT_SUPPORTED;
10609 }
10610
10611 /****************************************************************
10612  _spoolss_GetPrinterDriverPackagePath
10613 ****************************************************************/
10614
10615 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10616                                             struct spoolss_GetPrinterDriverPackagePath *r)
10617 {
10618         p->rng_fault_state = true;
10619         return WERR_NOT_SUPPORTED;
10620 }
10621
10622 /****************************************************************
10623  _spoolss_69
10624 ****************************************************************/
10625
10626 WERROR _spoolss_69(struct pipes_struct *p,
10627                    struct spoolss_69 *r)
10628 {
10629         p->rng_fault_state = true;
10630         return WERR_NOT_SUPPORTED;
10631 }
10632
10633 /****************************************************************
10634  _spoolss_6a
10635 ****************************************************************/
10636
10637 WERROR _spoolss_6a(struct pipes_struct *p,
10638                    struct spoolss_6a *r)
10639 {
10640         p->rng_fault_state = true;
10641         return WERR_NOT_SUPPORTED;
10642 }
10643
10644 /****************************************************************
10645  _spoolss_6b
10646 ****************************************************************/
10647
10648 WERROR _spoolss_6b(struct pipes_struct *p,
10649                    struct spoolss_6b *r)
10650 {
10651         p->rng_fault_state = true;
10652         return WERR_NOT_SUPPORTED;
10653 }
10654
10655 /****************************************************************
10656  _spoolss_6c
10657 ****************************************************************/
10658
10659 WERROR _spoolss_6c(struct pipes_struct *p,
10660                    struct spoolss_6c *r)
10661 {
10662         p->rng_fault_state = true;
10663         return WERR_NOT_SUPPORTED;
10664 }
10665
10666 /****************************************************************
10667  _spoolss_6d
10668 ****************************************************************/
10669
10670 WERROR _spoolss_6d(struct pipes_struct *p,
10671                    struct spoolss_6d *r)
10672 {
10673         p->rng_fault_state = true;
10674         return WERR_NOT_SUPPORTED;
10675 }