s3-spoolss: remove unused struct in construct_notify_printer_info().
[ddiss/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "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
55 /* macros stolen from s4 spoolss server */
56 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
57         ((info)?ndr_size_##fn(info, level, 0):0)
58
59 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
60         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
61
62 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
63         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
64
65 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
66
67 #undef DBGC_CLASS
68 #define DBGC_CLASS DBGC_RPC_SRV
69
70 #ifndef MAX_OPEN_PRINTER_EXS
71 #define MAX_OPEN_PRINTER_EXS 50
72 #endif
73
74 struct notify_back_channel;
75
76 /* structure to store the printer handles */
77 /* and a reference to what it's pointing to */
78 /* and the notify info asked about */
79 /* that's the central struct */
80 struct printer_handle {
81         struct printer_handle *prev, *next;
82         bool document_started;
83         bool page_started;
84         uint32 jobid; /* jobid in printing backend */
85         int printer_type;
86         const char *servername;
87         fstring sharename;
88         uint32 type;
89         uint32 access_granted;
90         struct {
91                 uint32 flags;
92                 uint32 options;
93                 fstring localmachine;
94                 uint32 printerlocal;
95                 struct spoolss_NotifyOption *option;
96                 struct policy_handle cli_hnd;
97                 struct notify_back_channel *cli_chan;
98                 uint32 change;
99                 /* are we in a FindNextPrinterChangeNotify() call? */
100                 bool fnpcn;
101                 struct messaging_context *msg_ctx;
102         } notify;
103         struct {
104                 fstring machine;
105                 fstring user;
106         } client;
107
108         /* devmode sent in the OpenPrinter() call */
109         struct spoolss_DeviceMode *devmode;
110
111         /* TODO cache the printer info2 structure */
112         struct spoolss_PrinterInfo2 *info2;
113
114 };
115
116 static struct printer_handle *printers_list;
117
118 struct printer_session_counter {
119         struct printer_session_counter *next;
120         struct printer_session_counter *prev;
121
122         int snum;
123         uint32_t counter;
124 };
125
126 static struct printer_session_counter *counter_list;
127
128 struct notify_back_channel {
129         struct notify_back_channel *prev, *next;
130
131         /* associated client */
132         struct sockaddr_storage client_address;
133
134         /* print notify back-channel pipe handle*/
135         struct rpc_pipe_client *cli_pipe;
136         struct dcerpc_binding_handle *binding_handle;
137         uint32_t active_connections;
138 };
139
140 static struct notify_back_channel *back_channels;
141
142 /* Map generic permissions to printer object specific permissions */
143
144 const struct standard_mapping printer_std_mapping = {
145         PRINTER_READ,
146         PRINTER_WRITE,
147         PRINTER_EXECUTE,
148         PRINTER_ALL_ACCESS
149 };
150
151 /* Map generic permissions to print server object specific permissions */
152
153 const struct standard_mapping printserver_std_mapping = {
154         SERVER_READ,
155         SERVER_WRITE,
156         SERVER_EXECUTE,
157         SERVER_ALL_ACCESS
158 };
159
160 /* API table for Xcv Monitor functions */
161
162 struct xcv_api_table {
163         const char *name;
164         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
165 };
166
167 static void prune_printername_cache(void);
168
169 /********************************************************************
170  * Canonicalize servername.
171  ********************************************************************/
172
173 static const char *canon_servername(const char *servername)
174 {
175         const char *pservername = servername;
176         while (*pservername == '\\') {
177                 pservername++;
178         }
179         return pservername;
180 }
181
182 /* translate between internal status numbers and NT status numbers */
183 static int nt_printj_status(int v)
184 {
185         switch (v) {
186         case LPQ_QUEUED:
187                 return 0;
188         case LPQ_PAUSED:
189                 return JOB_STATUS_PAUSED;
190         case LPQ_SPOOLING:
191                 return JOB_STATUS_SPOOLING;
192         case LPQ_PRINTING:
193                 return JOB_STATUS_PRINTING;
194         case LPQ_ERROR:
195                 return JOB_STATUS_ERROR;
196         case LPQ_DELETING:
197                 return JOB_STATUS_DELETING;
198         case LPQ_OFFLINE:
199                 return JOB_STATUS_OFFLINE;
200         case LPQ_PAPEROUT:
201                 return JOB_STATUS_PAPEROUT;
202         case LPQ_PRINTED:
203                 return JOB_STATUS_PRINTED;
204         case LPQ_DELETED:
205                 return JOB_STATUS_DELETED;
206         case LPQ_BLOCKED:
207                 return JOB_STATUS_BLOCKED_DEVQ;
208         case LPQ_USER_INTERVENTION:
209                 return JOB_STATUS_USER_INTERVENTION;
210         }
211         return 0;
212 }
213
214 static int nt_printq_status(int v)
215 {
216         switch (v) {
217         case LPQ_PAUSED:
218                 return PRINTER_STATUS_PAUSED;
219         case LPQ_QUEUED:
220         case LPQ_SPOOLING:
221         case LPQ_PRINTING:
222                 return 0;
223         }
224         return 0;
225 }
226
227 /***************************************************************************
228  Disconnect from the client
229 ****************************************************************************/
230
231 static void srv_spoolss_replycloseprinter(int snum,
232                                           struct printer_handle *prn_hnd)
233 {
234         WERROR result;
235         NTSTATUS status;
236
237         /*
238          * Tell the specific printing tdb we no longer want messages for this printer
239          * by deregistering our PID.
240          */
241
242         if (!print_notify_deregister_pid(snum)) {
243                 DEBUG(0, ("Failed to register our pid for printer %s\n",
244                           lp_const_servicename(snum)));
245         }
246
247         /* weird if the test succeeds !!! */
248         if (prn_hnd->notify.cli_chan == NULL ||
249             prn_hnd->notify.cli_chan->active_connections == 0) {
250                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
251                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
252                 TALLOC_FREE(prn_hnd->notify.cli_chan);
253                 return;
254         }
255
256         status = dcerpc_spoolss_ReplyClosePrinter(
257                                         prn_hnd->notify.cli_chan->binding_handle,
258                                         talloc_tos(),
259                                         &prn_hnd->notify.cli_hnd,
260                                         &result);
261         if (!NT_STATUS_IS_OK(status)) {
262                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
263                           nt_errstr(status)));
264                 result = ntstatus_to_werror(status);
265         } else if (!W_ERROR_IS_OK(result)) {
266                 DEBUG(0, ("reply_close_printer failed [%s].\n",
267                           win_errstr(result)));
268         }
269
270         /* if it's the last connection, deconnect the IPC$ share */
271         if (prn_hnd->notify.cli_chan->active_connections == 1) {
272
273                 prn_hnd->notify.cli_chan->binding_handle = NULL;
274                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
275                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
276                 TALLOC_FREE(prn_hnd->notify.cli_chan);
277
278                 if (prn_hnd->notify.msg_ctx != NULL) {
279                         messaging_deregister(prn_hnd->notify.msg_ctx,
280                                              MSG_PRINTER_NOTIFY2, NULL);
281
282                         /*
283                          * Tell the serverid.tdb we're no longer
284                          * interested in printer notify messages.
285                          */
286
287                         serverid_register_msg_flags(
288                                 messaging_server_id(prn_hnd->notify.msg_ctx),
289                                 false, FLAG_MSG_PRINT_NOTIFY);
290                 }
291         }
292
293         if (prn_hnd->notify.cli_chan) {
294                 prn_hnd->notify.cli_chan->active_connections--;
295         }
296 }
297
298 /****************************************************************************
299  Functions to free a printer entry datastruct.
300 ****************************************************************************/
301
302 static int printer_entry_destructor(struct printer_handle *Printer)
303 {
304         if (Printer->notify.cli_chan != NULL &&
305             Printer->notify.cli_chan->active_connections > 0) {
306                 int snum = -1;
307
308                 switch(Printer->printer_type) {
309                 case SPLHND_SERVER:
310                         srv_spoolss_replycloseprinter(snum, Printer);
311                         break;
312
313                 case SPLHND_PRINTER:
314                         snum = print_queue_snum(Printer->sharename);
315                         if (snum != -1) {
316                                 srv_spoolss_replycloseprinter(snum, Printer);
317                         }
318                         break;
319                 default:
320                         break;
321                 }
322         }
323
324         Printer->notify.flags=0;
325         Printer->notify.options=0;
326         Printer->notify.localmachine[0]='\0';
327         Printer->notify.printerlocal=0;
328         TALLOC_FREE(Printer->notify.option);
329         TALLOC_FREE(Printer->devmode);
330
331         /* Remove from the internal list. */
332         DLIST_REMOVE(printers_list, Printer);
333         return 0;
334 }
335
336 /****************************************************************************
337   find printer index by handle
338 ****************************************************************************/
339
340 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
341                                                         struct policy_handle *hnd)
342 {
343         struct printer_handle *find_printer = NULL;
344
345         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
346                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
347                 return NULL;
348         }
349
350         return find_printer;
351 }
352
353 /****************************************************************************
354  Close printer index by handle.
355 ****************************************************************************/
356
357 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
358 {
359         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
360
361         if (!Printer) {
362                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
363                         OUR_HANDLE(hnd)));
364                 return false;
365         }
366
367         close_policy_hnd(p, hnd);
368
369         return true;
370 }
371
372 /****************************************************************************
373  Delete a printer given a handle.
374 ****************************************************************************/
375
376 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
377                                   const char *sharename,
378                                   struct messaging_context *msg_ctx)
379 {
380         char *cmd = lp_deleteprinter_cmd();
381         char *command = NULL;
382         int ret;
383         bool is_print_op = false;
384
385         /* can't fail if we don't try */
386
387         if ( !*cmd )
388                 return WERR_OK;
389
390         command = talloc_asprintf(ctx,
391                         "%s \"%s\"",
392                         cmd, sharename);
393         if (!command) {
394                 return WERR_NOMEM;
395         }
396         if ( token )
397                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
398
399         DEBUG(10,("Running [%s]\n", command));
400
401         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
402
403         if ( is_print_op )
404                 become_root();
405
406         if ( (ret = smbrun(command, NULL)) == 0 ) {
407                 /* Tell everyone we updated smb.conf. */
408                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
409         }
410
411         if ( is_print_op )
412                 unbecome_root();
413
414         /********** END SePrintOperatorPrivlege BLOCK **********/
415
416         DEBUGADD(10,("returned [%d]\n", ret));
417
418         TALLOC_FREE(command);
419
420         if (ret != 0)
421                 return WERR_BADFID; /* What to return here? */
422
423         /* go ahead and re-read the services immediately */
424         become_root();
425         reload_services(msg_ctx, -1, false);
426         unbecome_root();
427
428         if ( lp_servicenumber( sharename ) >= 0 )
429                 return WERR_ACCESS_DENIED;
430
431         return WERR_OK;
432 }
433
434 /****************************************************************************
435  Delete a printer given a handle.
436 ****************************************************************************/
437
438 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
439 {
440         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
441         WERROR result;
442
443         if (!Printer) {
444                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
445                         OUR_HANDLE(hnd)));
446                 return WERR_BADFID;
447         }
448
449         /*
450          * It turns out that Windows allows delete printer on a handle
451          * opened by an admin user, then used on a pipe handle created
452          * by an anonymous user..... but they're working on security.... riiight !
453          * JRA.
454          */
455
456         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
457                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
458                 return WERR_ACCESS_DENIED;
459         }
460
461         /* this does not need a become root since the access check has been
462            done on the handle already */
463
464         result = winreg_delete_printer_key(p->mem_ctx,
465                                            get_session_info_system(),
466                                            p->msg_ctx,
467                                            Printer->sharename,
468                                            "");
469         if (!W_ERROR_IS_OK(result)) {
470                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
471                 return WERR_BADFID;
472         }
473
474         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
475                                      Printer->sharename, p->msg_ctx);
476         if (!W_ERROR_IS_OK(result)) {
477                 return result;
478         }
479         prune_printername_cache();
480         return WERR_OK;
481 }
482
483 /****************************************************************************
484  Return the snum of a printer corresponding to an handle.
485 ****************************************************************************/
486
487 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
488                              int *number, struct share_params **params)
489 {
490         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
491
492         if (!Printer) {
493                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
494                         OUR_HANDLE(hnd)));
495                 return false;
496         }
497
498         switch (Printer->printer_type) {
499                 case SPLHND_PRINTER:
500                         DEBUG(4,("short name:%s\n", Printer->sharename));
501                         *number = print_queue_snum(Printer->sharename);
502                         return (*number != -1);
503                 case SPLHND_SERVER:
504                         return false;
505                 default:
506                         return false;
507         }
508 }
509
510 /****************************************************************************
511  Set printer handle type.
512  Check if it's \\server or \\server\printer
513 ****************************************************************************/
514
515 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
516 {
517         DEBUG(3,("Setting printer type=%s\n", handlename));
518
519         /* it's a print server */
520         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
521                 DEBUGADD(4,("Printer is a print server\n"));
522                 Printer->printer_type = SPLHND_SERVER;
523         }
524         /* it's a printer (set_printer_hnd_name() will handle port monitors */
525         else {
526                 DEBUGADD(4,("Printer is a printer\n"));
527                 Printer->printer_type = SPLHND_PRINTER;
528         }
529
530         return true;
531 }
532
533 static void prune_printername_cache_fn(const char *key, const char *value,
534                                        time_t timeout, void *private_data)
535 {
536         gencache_del(key);
537 }
538
539 static void prune_printername_cache(void)
540 {
541         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
542 }
543
544 /****************************************************************************
545  Set printer handle name..  Accept names like \\server, \\server\printer,
546  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
547  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
548  XcvDataPort() interface.
549 ****************************************************************************/
550
551 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
552                                    const struct auth_serversupplied_info *session_info,
553                                    struct messaging_context *msg_ctx,
554                                    struct printer_handle *Printer,
555                                    const char *handlename)
556 {
557         int snum;
558         int n_services=lp_numservices();
559         char *aprinter;
560         const char *printername;
561         const char *servername = NULL;
562         fstring sname;
563         bool found = false;
564         struct spoolss_PrinterInfo2 *info2 = NULL;
565         WERROR result;
566         char *p;
567
568         /*
569          * Hopefully nobody names his printers like this. Maybe \ or ,
570          * are illegal in printer names even?
571          */
572         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
573         char *cache_key;
574         char *tmp;
575
576         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
577                 (unsigned long)strlen(handlename)));
578
579         aprinter = discard_const_p(char, handlename);
580         if ( *handlename == '\\' ) {
581                 servername = canon_servername(handlename);
582                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
583                         *aprinter = '\0';
584                         aprinter++;
585                 }
586                 if (!is_myname_or_ipaddr(servername)) {
587                         return WERR_INVALID_PRINTER_NAME;
588                 }
589                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
590                 if (Printer->servername == NULL) {
591                         return WERR_NOMEM;
592                 }
593         }
594
595         if (Printer->printer_type == SPLHND_SERVER) {
596                 return WERR_OK;
597         }
598
599         if (Printer->printer_type != SPLHND_PRINTER) {
600                 return WERR_INVALID_HANDLE;
601         }
602
603         DEBUGADD(5, ("searching for [%s]\n", aprinter));
604
605         p = strchr(aprinter, ',');
606         if (p != NULL) {
607                 char *p2 = p;
608                 p++;
609                 if (*p == ' ') {
610                         p++;
611                 }
612                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
613                         *p2 = '\0';
614                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
615                         *p2 = '\0';
616                 }
617         }
618
619         if (p) {
620                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
621         }
622
623         /* check for the Port Monitor Interface */
624         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
625                 Printer->printer_type = SPLHND_PORTMON_TCP;
626                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
627                 found = true;
628         }
629         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
630                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
631                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
632                 found = true;
633         }
634
635         /*
636          * With hundreds of printers, the "for" loop iterating all
637          * shares can be quite expensive, as it is done on every
638          * OpenPrinter. The loop maps "aprinter" to "sname", the
639          * result of which we cache in gencache.
640          */
641
642         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
643                                     aprinter);
644         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
645
646                 found = (strcmp(tmp, printer_not_found) != 0);
647                 if (!found) {
648                         DEBUG(4, ("Printer %s not found\n", aprinter));
649                         SAFE_FREE(tmp);
650                         return WERR_INVALID_PRINTER_NAME;
651                 }
652                 fstrcpy(sname, tmp);
653                 SAFE_FREE(tmp);
654         }
655
656         /* Search all sharenames first as this is easier than pulling
657            the printer_info_2 off of disk. Don't use find_service() since
658            that calls out to map_username() */
659
660         /* do another loop to look for printernames */
661         for (snum = 0; !found && snum < n_services; snum++) {
662                 const char *printer = lp_const_servicename(snum);
663
664                 /* no point going on if this is not a printer */
665                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
666                         continue;
667                 }
668
669                 /* ignore [printers] share */
670                 if (strequal(printer, "printers")) {
671                         continue;
672                 }
673
674                 fstrcpy(sname, printer);
675                 if (strequal(aprinter, printer)) {
676                         found = true;
677                         break;
678                 }
679
680                 /* no point looking up the printer object if
681                    we aren't allowing printername != sharename */
682                 if (lp_force_printername(snum)) {
683                         continue;
684                 }
685
686                 result = winreg_get_printer(mem_ctx,
687                                             session_info,
688                                             msg_ctx,
689                                             sname,
690                                             &info2);
691                 if ( !W_ERROR_IS_OK(result) ) {
692                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
693                                  sname, win_errstr(result)));
694                         continue;
695                 }
696
697                 printername = strrchr(info2->printername, '\\');
698                 if (printername == NULL) {
699                         printername = info2->printername;
700                 } else {
701                         printername++;
702                 }
703
704                 if (strequal(printername, aprinter)) {
705                         found = true;
706                         break;
707                 }
708
709                 DEBUGADD(10, ("printername: %s\n", printername));
710
711                 TALLOC_FREE(info2);
712         }
713
714         if ( !found ) {
715                 if (cache_key != NULL) {
716                         gencache_set(cache_key, printer_not_found,
717                                      time(NULL)+300);
718                         TALLOC_FREE(cache_key);
719                 }
720                 DEBUGADD(4,("Printer not found\n"));
721                 return WERR_INVALID_PRINTER_NAME;
722         }
723
724         if (cache_key != NULL) {
725                 gencache_set(cache_key, sname, time(NULL)+300);
726                 TALLOC_FREE(cache_key);
727         }
728
729         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
730
731         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
732
733         return WERR_OK;
734 }
735
736 /****************************************************************************
737  Find first available printer slot. creates a printer handle for you.
738  ****************************************************************************/
739
740 static WERROR open_printer_hnd(struct pipes_struct *p,
741                                struct policy_handle *hnd,
742                                const char *name,
743                                uint32_t access_granted)
744 {
745         struct printer_handle *new_printer;
746         WERROR result;
747
748         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
749
750         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
751         if (new_printer == NULL) {
752                 return WERR_NOMEM;
753         }
754         talloc_set_destructor(new_printer, printer_entry_destructor);
755
756         /* This also steals the printer_handle on the policy_handle */
757         if (!create_policy_hnd(p, hnd, new_printer)) {
758                 TALLOC_FREE(new_printer);
759                 return WERR_INVALID_HANDLE;
760         }
761
762         /* Add to the internal list. */
763         DLIST_ADD(printers_list, new_printer);
764
765         new_printer->notify.option=NULL;
766
767         if (!set_printer_hnd_printertype(new_printer, name)) {
768                 close_printer_handle(p, hnd);
769                 return WERR_INVALID_HANDLE;
770         }
771
772         result = set_printer_hnd_name(p->mem_ctx,
773                                       get_session_info_system(),
774                                       p->msg_ctx,
775                                       new_printer, name);
776         if (!W_ERROR_IS_OK(result)) {
777                 close_printer_handle(p, hnd);
778                 return result;
779         }
780
781         new_printer->access_granted = access_granted;
782
783         DEBUG(5, ("%d printer handles active\n",
784                   (int)num_pipe_handles(p)));
785
786         return WERR_OK;
787 }
788
789 /***************************************************************************
790  check to see if the client motify handle is monitoring the notification
791  given by (notify_type, notify_field).
792  **************************************************************************/
793
794 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
795                                       uint16_t notify_field)
796 {
797         return true;
798 }
799
800 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
801                                 uint16_t notify_field)
802 {
803         struct spoolss_NotifyOption *option = p->notify.option;
804         uint32_t i, j;
805
806         /*
807          * Flags should always be zero when the change notify
808          * is registered by the client's spooler.  A user Win32 app
809          * might use the flags though instead of the NOTIFY_OPTION_INFO
810          * --jerry
811          */
812
813         if (!option) {
814                 return false;
815         }
816
817         if (p->notify.flags)
818                 return is_monitoring_event_flags(
819                         p->notify.flags, notify_type, notify_field);
820
821         for (i = 0; i < option->count; i++) {
822
823                 /* Check match for notify_type */
824
825                 if (option->types[i].type != notify_type)
826                         continue;
827
828                 /* Check match for field */
829
830                 for (j = 0; j < option->types[i].count; j++) {
831                         if (option->types[i].fields[j].field == notify_field) {
832                                 return true;
833                         }
834                 }
835         }
836
837         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
838                    p->servername, p->sharename, notify_type, notify_field));
839
840         return false;
841 }
842
843 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
844         _data->data.integer[0] = _integer; \
845         _data->data.integer[1] = 0;
846
847
848 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
849         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
850         if (!_data->data.string.string) {\
851                 _data->data.string.size = 0; \
852         } \
853         _data->data.string.size = strlen_m_term(_p) * 2;
854
855 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
856         _data->data.devmode.devmode = _devmode;
857
858 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
859         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
860         if (!_data->data.sd.sd) { \
861                 _data->data.sd.sd_size = 0; \
862         } \
863         _data->data.sd.sd_size = \
864                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
865
866 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
867                                    struct tm *t,
868                                    const char **pp,
869                                    uint32_t *plen)
870 {
871         struct spoolss_Time st;
872         uint32_t len = 16;
873         char *p;
874
875         if (!init_systemtime(&st, t)) {
876                 return;
877         }
878
879         p = talloc_array(mem_ctx, char, len);
880         if (!p) {
881                 return;
882         }
883
884         /*
885          * Systemtime must be linearized as a set of UINT16's.
886          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
887          */
888
889         SSVAL(p, 0, st.year);
890         SSVAL(p, 2, st.month);
891         SSVAL(p, 4, st.day_of_week);
892         SSVAL(p, 6, st.day);
893         SSVAL(p, 8, st.hour);
894         SSVAL(p, 10, st.minute);
895         SSVAL(p, 12, st.second);
896         SSVAL(p, 14, st.millisecond);
897
898         *pp = p;
899         *plen = len;
900 }
901
902 /* Convert a notification message to a struct spoolss_Notify */
903
904 static void notify_one_value(struct spoolss_notify_msg *msg,
905                              struct spoolss_Notify *data,
906                              TALLOC_CTX *mem_ctx)
907 {
908         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
909 }
910
911 static void notify_string(struct spoolss_notify_msg *msg,
912                           struct spoolss_Notify *data,
913                           TALLOC_CTX *mem_ctx)
914 {
915         /* The length of the message includes the trailing \0 */
916
917         data->data.string.size = msg->len * 2;
918         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
919         if (!data->data.string.string) {
920                 data->data.string.size = 0;
921                 return;
922         }
923 }
924
925 static void notify_system_time(struct spoolss_notify_msg *msg,
926                                struct spoolss_Notify *data,
927                                TALLOC_CTX *mem_ctx)
928 {
929         data->data.string.string = NULL;
930         data->data.string.size = 0;
931
932         if (msg->len != sizeof(time_t)) {
933                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
934                           msg->len));
935                 return;
936         }
937
938         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
939                                &data->data.string.string,
940                                &data->data.string.size);
941 }
942
943 struct notify2_message_table {
944         const char *name;
945         void (*fn)(struct spoolss_notify_msg *msg,
946                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
947 };
948
949 static struct notify2_message_table printer_notify_table[] = {
950         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
951         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
952         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
953         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
954         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
955         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
956         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
957         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
958         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
959         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
960         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
961         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
962         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
963         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
964         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
965         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
966         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
967         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
968         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
969 };
970
971 static struct notify2_message_table job_notify_table[] = {
972         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
973         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
974         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
975         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
976         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
977         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
978         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
979         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
980         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
981         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
982         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
983         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
984         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
985         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
986         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
987         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
988         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
989         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
990         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
991         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
992         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
993         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
994         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
995         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
996 };
997
998
999 /***********************************************************************
1000  Allocate talloc context for container object
1001  **********************************************************************/
1002
1003 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1004 {
1005         if ( !ctr )
1006                 return;
1007
1008         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1009
1010         return;
1011 }
1012
1013 /***********************************************************************
1014  release all allocated memory and zero out structure
1015  **********************************************************************/
1016
1017 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1018 {
1019         if ( !ctr )
1020                 return;
1021
1022         if ( ctr->ctx )
1023                 talloc_destroy(ctr->ctx);
1024
1025         ZERO_STRUCTP(ctr);
1026
1027         return;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1034 {
1035         if ( !ctr )
1036                 return NULL;
1037
1038         return ctr->ctx;
1039 }
1040
1041 /***********************************************************************
1042  **********************************************************************/
1043
1044 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1045 {
1046         if ( !ctr || !ctr->msg_groups )
1047                 return NULL;
1048
1049         if ( idx >= ctr->num_groups )
1050                 return NULL;
1051
1052         return &ctr->msg_groups[idx];
1053
1054 }
1055
1056 /***********************************************************************
1057  How many groups of change messages do we have ?
1058  **********************************************************************/
1059
1060 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1061 {
1062         if ( !ctr )
1063                 return 0;
1064
1065         return ctr->num_groups;
1066 }
1067
1068 /***********************************************************************
1069  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1070  **********************************************************************/
1071
1072 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1073 {
1074         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1075         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1076         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1077         int                             i, new_slot;
1078
1079         if ( !ctr || !msg )
1080                 return 0;
1081
1082         /* loop over all groups looking for a matching printer name */
1083
1084         for ( i=0; i<ctr->num_groups; i++ ) {
1085                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1086                         break;
1087         }
1088
1089         /* add a new group? */
1090
1091         if ( i == ctr->num_groups ) {
1092                 ctr->num_groups++;
1093
1094                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1095                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1096                         return 0;
1097                 }
1098                 ctr->msg_groups = groups;
1099
1100                 /* clear the new entry and set the printer name */
1101
1102                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1103                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1104         }
1105
1106         /* add the change messages; 'i' is the correct index now regardless */
1107
1108         msg_grp = &ctr->msg_groups[i];
1109
1110         msg_grp->num_msgs++;
1111
1112         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1113                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1114                 return 0;
1115         }
1116         msg_grp->msgs = msg_list;
1117
1118         new_slot = msg_grp->num_msgs-1;
1119         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1120
1121         /* need to allocate own copy of data */
1122
1123         if ( msg->len != 0 )
1124                 msg_grp->msgs[new_slot].notify.data = (char *)
1125                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1126
1127         return ctr->num_groups;
1128 }
1129
1130 static void construct_info_data(struct spoolss_Notify *info_data,
1131                                 enum spoolss_NotifyType type,
1132                                 uint16_t field, int id);
1133
1134 /***********************************************************************
1135  Send a change notication message on all handles which have a call
1136  back registered
1137  **********************************************************************/
1138
1139 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1140                                   struct printer_handle *prn_hnd,
1141                                   SPOOLSS_NOTIFY_MSG *messages,
1142                                   uint32_t num_msgs,
1143                                   struct spoolss_Notify **_notifies,
1144                                   int *_count)
1145 {
1146         struct spoolss_Notify *notifies;
1147         SPOOLSS_NOTIFY_MSG *msg;
1148         int count = 0;
1149         uint32_t id;
1150         int i;
1151
1152         notifies = talloc_zero_array(mem_ctx,
1153                                      struct spoolss_Notify, num_msgs);
1154         if (!notifies) {
1155                 return ENOMEM;
1156         }
1157
1158         for (i = 0; i < num_msgs; i++) {
1159
1160                 msg = &messages[i];
1161
1162                 /* Are we monitoring this event? */
1163
1164                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1165                         continue;
1166                 }
1167
1168                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1169                            "for printer [%s]\n",
1170                            msg->type, msg->field, prn_hnd->sharename));
1171
1172                 /*
1173                  * if the is a printer notification handle and not a job
1174                  * notification type, then set the id to 0.
1175                  * Otherwise just use what was specified in the message.
1176                  *
1177                  * When registering change notification on a print server
1178                  * handle we always need to send back the id (snum) matching
1179                  * the printer for which the change took place.
1180                  * For change notify registered on a printer handle,
1181                  * this does not matter and the id should be 0.
1182                  *
1183                  * --jerry
1184                  */
1185
1186                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1187                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1188                         id = 0;
1189                 } else {
1190                         id = msg->id;
1191                 }
1192
1193                 /* Convert unix jobid to smb jobid */
1194
1195                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1196                         id = sysjob_to_jobid(msg->id);
1197
1198                         if (id == -1) {
1199                                 DEBUG(3, ("no such unix jobid %d\n",
1200                                           msg->id));
1201                                 continue;
1202                         }
1203                 }
1204
1205                 construct_info_data(&notifies[count],
1206                                     msg->type, msg->field, id);
1207
1208                 switch(msg->type) {
1209                 case PRINTER_NOTIFY_TYPE:
1210                         if (printer_notify_table[msg->field].fn) {
1211                                 printer_notify_table[msg->field].fn(msg,
1212                                                 &notifies[count], mem_ctx);
1213                         }
1214                         break;
1215
1216                 case JOB_NOTIFY_TYPE:
1217                         if (job_notify_table[msg->field].fn) {
1218                                 job_notify_table[msg->field].fn(msg,
1219                                                 &notifies[count], mem_ctx);
1220                         }
1221                         break;
1222
1223                 default:
1224                         DEBUG(5, ("Unknown notification type %d\n",
1225                                   msg->type));
1226                         continue;
1227                 }
1228
1229                 count++;
1230         }
1231
1232         *_notifies = notifies;
1233         *_count = count;
1234
1235         return 0;
1236 }
1237
1238 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1239                                 struct printer_handle *prn_hnd,
1240                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1241 {
1242         struct spoolss_Notify *notifies;
1243         int count = 0;
1244         union spoolss_ReplyPrinterInfo info;
1245         struct spoolss_NotifyInfo info0;
1246         uint32_t reply_result;
1247         NTSTATUS status;
1248         WERROR werr;
1249         int ret;
1250
1251         /* Is there notification on this handle? */
1252         if (prn_hnd->notify.cli_chan == NULL ||
1253             prn_hnd->notify.cli_chan->active_connections == 0) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1258                    prn_hnd->servername, prn_hnd->sharename));
1259
1260         /* For this printer? Print servers always receive notifications. */
1261         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1262             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1263                 return 0;
1264         }
1265
1266         DEBUG(10,("Our printer\n"));
1267
1268         /* build the array of change notifications */
1269         ret = build_notify2_messages(mem_ctx, prn_hnd,
1270                                      msg_group->msgs,
1271                                      msg_group->num_msgs,
1272                                      &notifies, &count);
1273         if (ret) {
1274                 return ret;
1275         }
1276
1277         info0.version   = 0x2;
1278         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1279         info0.count     = count;
1280         info0.notifies  = notifies;
1281
1282         info.info0 = &info0;
1283
1284         status = dcerpc_spoolss_RouterReplyPrinterEx(
1285                                 prn_hnd->notify.cli_chan->binding_handle,
1286                                 mem_ctx,
1287                                 &prn_hnd->notify.cli_hnd,
1288                                 prn_hnd->notify.change, /* color */
1289                                 prn_hnd->notify.flags,
1290                                 &reply_result,
1291                                 0, /* reply_type, must be 0 */
1292                                 info, &werr);
1293         if (!NT_STATUS_IS_OK(status)) {
1294                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1295                           "failed: %s\n",
1296                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1297                           nt_errstr(status)));
1298                 werr = ntstatus_to_werror(status);
1299         } else if (!W_ERROR_IS_OK(werr)) {
1300                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1301                           "failed: %s\n",
1302                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1303                           win_errstr(werr)));
1304         }
1305         switch (reply_result) {
1306         case 0:
1307                 break;
1308         case PRINTER_NOTIFY_INFO_DISCARDED:
1309         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1310         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1311                 break;
1312         default:
1313                 break;
1314         }
1315
1316         return 0;
1317 }
1318
1319 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1320 {
1321         struct printer_handle    *p;
1322         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1323         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1324         int ret;
1325
1326         if ( !msg_group ) {
1327                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1328                 return;
1329         }
1330
1331         if (!msg_group->msgs) {
1332                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1333                 return;
1334         }
1335
1336         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1337
1338         /* loop over all printers */
1339
1340         for (p = printers_list; p; p = p->next) {
1341                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1342                 if (ret) {
1343                         goto done;
1344                 }
1345         }
1346
1347 done:
1348         DEBUG(8,("send_notify2_changes: Exit...\n"));
1349         return;
1350 }
1351
1352 /***********************************************************************
1353  **********************************************************************/
1354
1355 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1356 {
1357
1358         uint32_t tv_sec, tv_usec;
1359         size_t offset = 0;
1360
1361         /* Unpack message */
1362
1363         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1364                              msg->printer);
1365
1366         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1367                                 &tv_sec, &tv_usec,
1368                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1369
1370         if (msg->len == 0)
1371                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1372                            &msg->notify.value[0], &msg->notify.value[1]);
1373         else
1374                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1375                            &msg->len, &msg->notify.data);
1376
1377         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1378                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1379
1380         tv->tv_sec = tv_sec;
1381         tv->tv_usec = tv_usec;
1382
1383         if (msg->len == 0)
1384                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1385                           msg->notify.value[1]));
1386         else
1387                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1388
1389         return true;
1390 }
1391
1392 /********************************************************************
1393  Receive a notify2 message list
1394  ********************************************************************/
1395
1396 static void receive_notify2_message_list(struct messaging_context *msg,
1397                                          void *private_data,
1398                                          uint32_t msg_type,
1399                                          struct server_id server_id,
1400                                          DATA_BLOB *data)
1401 {
1402         size_t                  msg_count, i;
1403         char                    *buf = (char *)data->data;
1404         char                    *msg_ptr;
1405         size_t                  msg_len;
1406         SPOOLSS_NOTIFY_MSG      notify;
1407         SPOOLSS_NOTIFY_MSG_CTR  messages;
1408         int                     num_groups;
1409
1410         if (data->length < 4) {
1411                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1412                 return;
1413         }
1414
1415         msg_count = IVAL(buf, 0);
1416         msg_ptr = buf + 4;
1417
1418         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1419
1420         if (msg_count == 0) {
1421                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1422                 return;
1423         }
1424
1425         /* initialize the container */
1426
1427         ZERO_STRUCT( messages );
1428         notify_msg_ctr_init( &messages );
1429
1430         /*
1431          * build message groups for each printer identified
1432          * in a change_notify msg.  Remember that a PCN message
1433          * includes the handle returned for the srv_spoolss_replyopenprinter()
1434          * call.  Therefore messages are grouped according to printer handle.
1435          */
1436
1437         for ( i=0; i<msg_count; i++ ) {
1438                 struct timeval msg_tv;
1439
1440                 if (msg_ptr + 4 - buf > data->length) {
1441                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1442                         return;
1443                 }
1444
1445                 msg_len = IVAL(msg_ptr,0);
1446                 msg_ptr += 4;
1447
1448                 if (msg_ptr + msg_len - buf > data->length) {
1449                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1450                         return;
1451                 }
1452
1453                 /* unpack messages */
1454
1455                 ZERO_STRUCT( notify );
1456                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1457                 msg_ptr += msg_len;
1458
1459                 /* add to correct list in container */
1460
1461                 notify_msg_ctr_addmsg( &messages, &notify );
1462
1463                 /* free memory that might have been allocated by notify2_unpack_msg() */
1464
1465                 if ( notify.len != 0 )
1466                         SAFE_FREE( notify.notify.data );
1467         }
1468
1469         /* process each group of messages */
1470
1471         num_groups = notify_msg_ctr_numgroups( &messages );
1472         for ( i=0; i<num_groups; i++ )
1473                 send_notify2_changes( &messages, i );
1474
1475
1476         /* cleanup */
1477
1478         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1479                 (uint32_t)msg_count ));
1480
1481         notify_msg_ctr_destroy( &messages );
1482
1483         return;
1484 }
1485
1486 /********************************************************************
1487  Send a message to ourself about new driver being installed
1488  so we can upgrade the information for each printer bound to this
1489  driver
1490  ********************************************************************/
1491
1492 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1493                                             struct messaging_context *msg_ctx)
1494 {
1495         int len = strlen(drivername);
1496
1497         if (!len)
1498                 return false;
1499
1500         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1501                 drivername));
1502
1503         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1504                            MSG_PRINTER_DRVUPGRADE,
1505                            (const uint8_t *)drivername, len+1);
1506
1507         return true;
1508 }
1509
1510 void srv_spoolss_cleanup(void)
1511 {
1512         struct printer_session_counter *session_counter;
1513
1514         for (session_counter = counter_list;
1515              session_counter != NULL;
1516              session_counter = counter_list) {
1517                 DLIST_REMOVE(counter_list, session_counter);
1518                 TALLOC_FREE(session_counter);
1519         }
1520 }
1521
1522 /**********************************************************************
1523  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1524  over all printers, upgrading ones as necessary
1525  **********************************************************************/
1526
1527 void do_drv_upgrade_printer(struct messaging_context *msg,
1528                             void *private_data,
1529                             uint32_t msg_type,
1530                             struct server_id server_id,
1531                             DATA_BLOB *data)
1532 {
1533         TALLOC_CTX *tmp_ctx;
1534         struct auth_serversupplied_info *session_info = NULL;
1535         struct spoolss_PrinterInfo2 *pinfo2;
1536         NTSTATUS status;
1537         WERROR result;
1538         const char *drivername;
1539         int snum;
1540         int n_services = lp_numservices();
1541
1542         tmp_ctx = talloc_new(NULL);
1543         if (!tmp_ctx) return;
1544
1545         status = make_session_info_system(tmp_ctx, &session_info);
1546         if (!NT_STATUS_IS_OK(status)) {
1547                 DEBUG(0, ("do_drv_upgrade_printer: "
1548                           "Could not create system session_info\n"));
1549                 goto done;
1550         }
1551
1552         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1553         if (!drivername) {
1554                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1555                 goto done;
1556         }
1557
1558         DEBUG(10, ("do_drv_upgrade_printer: "
1559                    "Got message for new driver [%s]\n", drivername));
1560
1561         /* Iterate the printer list */
1562
1563         for (snum = 0; snum < n_services; snum++) {
1564                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1565                         continue;
1566                 }
1567
1568                 /* ignore [printers] share */
1569                 if (strequal(lp_const_servicename(snum), "printers")) {
1570                         continue;
1571                 }
1572
1573                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1574                                             lp_const_servicename(snum),
1575                                             &pinfo2);
1576
1577                 if (!W_ERROR_IS_OK(result)) {
1578                         continue;
1579                 }
1580
1581                 if (!pinfo2->drivername) {
1582                         continue;
1583                 }
1584
1585                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1586                         continue;
1587                 }
1588
1589                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1590
1591                 /* all we care about currently is the change_id */
1592                 result = winreg_printer_update_changeid(tmp_ctx,
1593                                                         session_info,
1594                                                         msg,
1595                                                         pinfo2->printername);
1596
1597                 if (!W_ERROR_IS_OK(result)) {
1598                         DEBUG(3, ("do_drv_upgrade_printer: "
1599                                   "Failed to update changeid [%s]\n",
1600                                   win_errstr(result)));
1601                 }
1602         }
1603
1604         /* all done */
1605 done:
1606         talloc_free(tmp_ctx);
1607 }
1608
1609 /********************************************************************
1610  Update the cache for all printq's with a registered client
1611  connection
1612  ********************************************************************/
1613
1614 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1615 {
1616         struct printer_handle *printer = printers_list;
1617         int snum;
1618
1619         /* loop through all printers and update the cache where
1620            a client is connected */
1621         while (printer) {
1622                 if ((printer->printer_type == SPLHND_PRINTER) &&
1623                     ((printer->notify.cli_chan != NULL) &&
1624                      (printer->notify.cli_chan->active_connections > 0))) {
1625                         snum = print_queue_snum(printer->sharename);
1626                         print_queue_status(msg_ctx, snum, NULL, NULL);
1627                 }
1628
1629                 printer = printer->next;
1630         }
1631
1632         return;
1633 }
1634
1635 /****************************************************************
1636  _spoolss_OpenPrinter
1637 ****************************************************************/
1638
1639 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1640                             struct spoolss_OpenPrinter *r)
1641 {
1642         struct spoolss_OpenPrinterEx e;
1643         WERROR werr;
1644
1645         ZERO_STRUCT(e.in.userlevel);
1646
1647         e.in.printername        = r->in.printername;
1648         e.in.datatype           = r->in.datatype;
1649         e.in.devmode_ctr        = r->in.devmode_ctr;
1650         e.in.access_mask        = r->in.access_mask;
1651         e.in.level              = 0;
1652
1653         e.out.handle            = r->out.handle;
1654
1655         werr = _spoolss_OpenPrinterEx(p, &e);
1656
1657         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1658                 /* OpenPrinterEx returns this for a bad
1659                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1660                  * instead.
1661                  */
1662                 werr = WERR_INVALID_PRINTER_NAME;
1663         }
1664
1665         return werr;
1666 }
1667
1668 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1669                               struct spoolss_DeviceMode *orig,
1670                               struct spoolss_DeviceMode **dest)
1671 {
1672         struct spoolss_DeviceMode *dm;
1673
1674         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1675         if (!dm) {
1676                 return WERR_NOMEM;
1677         }
1678
1679         /* copy all values, then duplicate strings and structs */
1680         *dm = *orig;
1681
1682         dm->devicename = talloc_strdup(dm, orig->devicename);
1683         if (!dm->devicename) {
1684                 return WERR_NOMEM;
1685         }
1686         dm->formname = talloc_strdup(dm, orig->formname);
1687         if (!dm->formname) {
1688                 return WERR_NOMEM;
1689         }
1690         if (orig->driverextra_data.data) {
1691                 dm->driverextra_data.data =
1692                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1693                                         orig->driverextra_data.length);
1694                 if (!dm->driverextra_data.data) {
1695                         return WERR_NOMEM;
1696                 }
1697         }
1698
1699         *dest = dm;
1700         return WERR_OK;
1701 }
1702
1703 /****************************************************************
1704  _spoolss_OpenPrinterEx
1705 ****************************************************************/
1706
1707 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1708                               struct spoolss_OpenPrinterEx *r)
1709 {
1710         int snum;
1711         struct printer_handle *Printer=NULL;
1712         WERROR result;
1713
1714         if (!r->in.printername) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717
1718         if (r->in.level > 3) {
1719                 return WERR_INVALID_PARAM;
1720         }
1721         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1722             (r->in.level == 2 && !r->in.userlevel.level2) ||
1723             (r->in.level == 3 && !r->in.userlevel.level3)) {
1724                 return WERR_INVALID_PARAM;
1725         }
1726
1727         /* some sanity check because you can open a printer or a print server */
1728         /* aka: \\server\printer or \\server */
1729
1730         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1731
1732         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1733         if (!W_ERROR_IS_OK(result)) {
1734                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1735                         "for printer %s\n", r->in.printername));
1736                 ZERO_STRUCTP(r->out.handle);
1737                 return result;
1738         }
1739
1740         Printer = find_printer_index_by_hnd(p, r->out.handle);
1741         if ( !Printer ) {
1742                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1743                         "handle we created for printer %s\n", r->in.printername));
1744                 close_printer_handle(p, r->out.handle);
1745                 ZERO_STRUCTP(r->out.handle);
1746                 return WERR_INVALID_PARAM;
1747         }
1748
1749         /*
1750          * First case: the user is opening the print server:
1751          *
1752          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1753          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1754          *
1755          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1756          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1757          * or if the user is listed in the smb.conf printer admin parameter.
1758          *
1759          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1760          * client view printer folder, but does not show the MSAPW.
1761          *
1762          * Note: this test needs code to check access rights here too. Jeremy
1763          * could you look at this?
1764          *
1765          * Second case: the user is opening a printer:
1766          * NT doesn't let us connect to a printer if the connecting user
1767          * doesn't have print permission.
1768          *
1769          * Third case: user is opening a Port Monitor
1770          * access checks same as opening a handle to the print server.
1771          */
1772
1773         switch (Printer->printer_type )
1774         {
1775         case SPLHND_SERVER:
1776         case SPLHND_PORTMON_TCP:
1777         case SPLHND_PORTMON_LOCAL:
1778                 /* Printserver handles use global struct... */
1779
1780                 snum = -1;
1781
1782                 /* Map standard access rights to object specific access rights */
1783
1784                 se_map_standard(&r->in.access_mask,
1785                                 &printserver_std_mapping);
1786
1787                 /* Deny any object specific bits that don't apply to print
1788                    servers (i.e printer and job specific bits) */
1789
1790                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1791
1792                 if (r->in.access_mask &
1793                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1794                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1795                         close_printer_handle(p, r->out.handle);
1796                         ZERO_STRUCTP(r->out.handle);
1797                         return WERR_ACCESS_DENIED;
1798                 }
1799
1800                 /* Allow admin access */
1801
1802                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1803                 {
1804                         if (!lp_ms_add_printer_wizard()) {
1805                                 close_printer_handle(p, r->out.handle);
1806                                 ZERO_STRUCTP(r->out.handle);
1807                                 return WERR_ACCESS_DENIED;
1808                         }
1809
1810                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1811                            and not a printer admin, then fail */
1812
1813                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1814                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1815                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1816                             !token_contains_name_in_list(
1817                                     uidtoname(p->session_info->utok.uid),
1818                                     p->session_info->info3->base.domain.string,
1819                                     NULL,
1820                                     p->session_info->security_token,
1821                                     lp_printer_admin(snum))) {
1822                                 close_printer_handle(p, r->out.handle);
1823                                 ZERO_STRUCTP(r->out.handle);
1824                                 DEBUG(3,("access DENIED as user is not root, "
1825                                         "has no printoperator privilege, "
1826                                         "not a member of the printoperator builtin group and "
1827                                         "is not in printer admin list"));
1828                                 return WERR_ACCESS_DENIED;
1829                         }
1830
1831                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1832                 }
1833                 else
1834                 {
1835                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1836                 }
1837
1838                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1839                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1840
1841                 /* We fall through to return WERR_OK */
1842                 break;
1843
1844         case SPLHND_PRINTER:
1845                 /* NT doesn't let us connect to a printer if the connecting user
1846                    doesn't have print permission.  */
1847
1848                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1849                         close_printer_handle(p, r->out.handle);
1850                         ZERO_STRUCTP(r->out.handle);
1851                         return WERR_BADFID;
1852                 }
1853
1854                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1855                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1856                 }
1857
1858                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1859
1860                 /* map an empty access mask to the minimum access mask */
1861                 if (r->in.access_mask == 0x0)
1862                         r->in.access_mask = PRINTER_ACCESS_USE;
1863
1864                 /*
1865                  * If we are not serving the printer driver for this printer,
1866                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1867                  * will keep NT clients happy  --jerry
1868                  */
1869
1870                 if (lp_use_client_driver(snum)
1871                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1872                 {
1873                         r->in.access_mask = PRINTER_ACCESS_USE;
1874                 }
1875
1876                 /* check smb.conf parameters and the the sec_desc */
1877
1878                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1879                                   p->client_id->name, p->client_id->addr)) {
1880                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1881                         ZERO_STRUCTP(r->out.handle);
1882                         return WERR_ACCESS_DENIED;
1883                 }
1884
1885                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1886                                    p->session_info->security_token, snum) ||
1887                     !print_access_check(p->session_info,
1888                                         p->msg_ctx,
1889                                         snum,
1890                                         r->in.access_mask)) {
1891                         DEBUG(3, ("access DENIED for printer open\n"));
1892                         close_printer_handle(p, r->out.handle);
1893                         ZERO_STRUCTP(r->out.handle);
1894                         return WERR_ACCESS_DENIED;
1895                 }
1896
1897                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1898                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1899                         close_printer_handle(p, r->out.handle);
1900                         ZERO_STRUCTP(r->out.handle);
1901                         return WERR_ACCESS_DENIED;
1902                 }
1903
1904                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1905                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1906                 else
1907                         r->in.access_mask = PRINTER_ACCESS_USE;
1908
1909                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1910                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1911
1912                 winreg_create_printer(p->mem_ctx,
1913                                       get_session_info_system(),
1914                                       p->msg_ctx,
1915                                       lp_const_servicename(snum));
1916
1917                 break;
1918
1919         default:
1920                 /* sanity check to prevent programmer error */
1921                 ZERO_STRUCTP(r->out.handle);
1922                 return WERR_BADFID;
1923         }
1924
1925         Printer->access_granted = r->in.access_mask;
1926
1927         /*
1928          * If the client sent a devmode in the OpenPrinter() call, then
1929          * save it here in case we get a job submission on this handle
1930          */
1931
1932          if ((Printer->printer_type != SPLHND_SERVER) &&
1933              r->in.devmode_ctr.devmode) {
1934                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1935                                 &Printer->devmode);
1936          }
1937
1938 #if 0   /* JERRY -- I'm doubtful this is really effective */
1939         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1940            optimization in Windows 2000 clients  --jerry */
1941
1942         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1943                 && (RA_WIN2K == get_remote_arch()) )
1944         {
1945                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1946                 sys_usleep( 500000 );
1947         }
1948 #endif
1949
1950         return WERR_OK;
1951 }
1952
1953 /****************************************************************
1954  _spoolss_ClosePrinter
1955 ****************************************************************/
1956
1957 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1958                              struct spoolss_ClosePrinter *r)
1959 {
1960         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1961
1962         if (Printer && Printer->document_started) {
1963                 struct spoolss_EndDocPrinter e;
1964
1965                 e.in.handle = r->in.handle;
1966
1967                 _spoolss_EndDocPrinter(p, &e);
1968         }
1969
1970         if (!close_printer_handle(p, r->in.handle))
1971                 return WERR_BADFID;
1972
1973         /* clear the returned printer handle.  Observed behavior
1974            from Win2k server.  Don't think this really matters.
1975            Previous code just copied the value of the closed
1976            handle.    --jerry */
1977
1978         ZERO_STRUCTP(r->out.handle);
1979
1980         return WERR_OK;
1981 }
1982
1983 /****************************************************************
1984  _spoolss_DeletePrinter
1985 ****************************************************************/
1986
1987 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1988                               struct spoolss_DeletePrinter *r)
1989 {
1990         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1991         WERROR result;
1992         int snum;
1993
1994         if (Printer && Printer->document_started) {
1995                 struct spoolss_EndDocPrinter e;
1996
1997                 e.in.handle = r->in.handle;
1998
1999                 _spoolss_EndDocPrinter(p, &e);
2000         }
2001
2002         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2003                 winreg_delete_printer_key(p->mem_ctx,
2004                                           get_session_info_system(),
2005                                           p->msg_ctx,
2006                                           lp_const_servicename(snum),
2007                                           "");
2008         }
2009
2010         result = delete_printer_handle(p, r->in.handle);
2011
2012         return result;
2013 }
2014
2015 /*******************************************************************
2016  * static function to lookup the version id corresponding to an
2017  * long architecture string
2018  ******************************************************************/
2019
2020 static const struct print_architecture_table_node archi_table[]= {
2021
2022         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2023         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2024         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2025         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2026         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2027         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2028         {"Windows x64",          SPL_ARCH_X64,          3 },
2029         {NULL,                   "",            -1 }
2030 };
2031
2032 static int get_version_id(const char *arch)
2033 {
2034         int i;
2035
2036         for (i=0; archi_table[i].long_archi != NULL; i++)
2037         {
2038                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2039                         return (archi_table[i].version);
2040         }
2041
2042         return -1;
2043 }
2044
2045 /****************************************************************
2046  _spoolss_DeletePrinterDriver
2047 ****************************************************************/
2048
2049 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2050                                     struct spoolss_DeletePrinterDriver *r)
2051 {
2052
2053         struct spoolss_DriverInfo8 *info = NULL;
2054         struct spoolss_DriverInfo8 *info_win2k = NULL;
2055         int                             version;
2056         WERROR                          status;
2057
2058         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2059            and not a printer admin, then fail */
2060
2061         if ( (p->session_info->utok.uid != sec_initial_uid())
2062              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2063                 && !token_contains_name_in_list(
2064                         uidtoname(p->session_info->utok.uid),
2065                         p->session_info->info3->base.domain.string,
2066                         NULL,
2067                         p->session_info->security_token,
2068                         lp_printer_admin(-1)) )
2069         {
2070                 return WERR_ACCESS_DENIED;
2071         }
2072
2073         /* check that we have a valid driver name first */
2074
2075         if ((version = get_version_id(r->in.architecture)) == -1)
2076                 return WERR_INVALID_ENVIRONMENT;
2077
2078         status = winreg_get_driver(p->mem_ctx,
2079                                    get_session_info_system(),
2080                                    p->msg_ctx,
2081                                    r->in.architecture, r->in.driver,
2082                                    version, &info);
2083         if (!W_ERROR_IS_OK(status)) {
2084                 /* try for Win2k driver if "Windows NT x86" */
2085
2086                 if ( version == 2 ) {
2087                         version = 3;
2088
2089                         status = winreg_get_driver(p->mem_ctx,
2090                                                    get_session_info_system(),
2091                                                    p->msg_ctx,
2092                                                    r->in.architecture,
2093                                                    r->in.driver,
2094                                                    version, &info);
2095                         if (!W_ERROR_IS_OK(status)) {
2096                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2097                                 goto done;
2098                         }
2099                 }
2100                 /* otherwise it was a failure */
2101                 else {
2102                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2103                         goto done;
2104                 }
2105
2106         }
2107
2108         if (printer_driver_in_use(p->mem_ctx,
2109                                   get_session_info_system(),
2110                                   p->msg_ctx,
2111                                   info)) {
2112                 status = WERR_PRINTER_DRIVER_IN_USE;
2113                 goto done;
2114         }
2115
2116         if (version == 2) {
2117                 status = winreg_get_driver(p->mem_ctx,
2118                                            get_session_info_system(),
2119                                            p->msg_ctx,
2120                                            r->in.architecture,
2121                                            r->in.driver, 3, &info_win2k);
2122                 if (W_ERROR_IS_OK(status)) {
2123                         /* if we get to here, we now have 2 driver info structures to remove */
2124                         /* remove the Win2k driver first*/
2125
2126                         status = winreg_del_driver(p->mem_ctx,
2127                                                    get_session_info_system(),
2128                                                    p->msg_ctx,
2129                                                    info_win2k, 3);
2130                         talloc_free(info_win2k);
2131
2132                         /* this should not have failed---if it did, report to client */
2133                         if (!W_ERROR_IS_OK(status)) {
2134                                 goto done;
2135                         }
2136                 }
2137         }
2138
2139         status = winreg_del_driver(p->mem_ctx,
2140                                    get_session_info_system(),
2141                                    p->msg_ctx,
2142                                    info, version);
2143
2144 done:
2145         talloc_free(info);
2146
2147         return status;
2148 }
2149
2150 /****************************************************************
2151  _spoolss_DeletePrinterDriverEx
2152 ****************************************************************/
2153
2154 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2155                                       struct spoolss_DeletePrinterDriverEx *r)
2156 {
2157         struct spoolss_DriverInfo8      *info = NULL;
2158         struct spoolss_DriverInfo8      *info_win2k = NULL;
2159         int                             version;
2160         bool                            delete_files;
2161         WERROR                          status;
2162
2163         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2164            and not a printer admin, then fail */
2165
2166         if ( (p->session_info->utok.uid != sec_initial_uid())
2167                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2168                 && !token_contains_name_in_list(
2169                         uidtoname(p->session_info->utok.uid),
2170                         p->session_info->info3->base.domain.string,
2171                         NULL,
2172                         p->session_info->security_token, lp_printer_admin(-1)) )
2173         {
2174                 return WERR_ACCESS_DENIED;
2175         }
2176
2177         /* check that we have a valid driver name first */
2178         if ((version = get_version_id(r->in.architecture)) == -1) {
2179                 /* this is what NT returns */
2180                 return WERR_INVALID_ENVIRONMENT;
2181         }
2182
2183         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2184                 version = r->in.version;
2185
2186         status = winreg_get_driver(p->mem_ctx,
2187                                    get_session_info_system(),
2188                                    p->msg_ctx,
2189                                    r->in.architecture,
2190                                    r->in.driver,
2191                                    version,
2192                                    &info);
2193         if (!W_ERROR_IS_OK(status)) {
2194                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2195
2196                 /*
2197                  * if the client asked for a specific version,
2198                  * or this is something other than Windows NT x86,
2199                  * then we've failed
2200                  */
2201
2202                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2203                         goto done;
2204
2205                 /* try for Win2k driver if "Windows NT x86" */
2206
2207                 version = 3;
2208                 status = winreg_get_driver(info,
2209                                            get_session_info_system(),
2210                                            p->msg_ctx,
2211                                            r->in.architecture,
2212                                            r->in.driver,
2213                                            version, &info);
2214                 if (!W_ERROR_IS_OK(status)) {
2215                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2216                         goto done;
2217                 }
2218         }
2219
2220         if (printer_driver_in_use(info,
2221                                   get_session_info_system(),
2222                                   p->msg_ctx,
2223                                   info)) {
2224                 status = WERR_PRINTER_DRIVER_IN_USE;
2225                 goto done;
2226         }
2227
2228         /*
2229          * we have a couple of cases to consider.
2230          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2231          *     then the delete should fail if **any** files overlap with
2232          *     other drivers
2233          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2234          *     non-overlapping files
2235          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2236          *     is set, the do not delete any files
2237          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2238          */
2239
2240         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2241
2242         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2243
2244         if (delete_files &&
2245             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2246             printer_driver_files_in_use(info,
2247                                         get_session_info_system(),
2248                                         p->msg_ctx,
2249                                         info)) {
2250                 /* no idea of the correct error here */
2251                 status = WERR_ACCESS_DENIED;
2252                 goto done;
2253         }
2254
2255
2256         /* also check for W32X86/3 if necessary; maybe we already have? */
2257
2258         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2259                 status = winreg_get_driver(info,
2260                                            get_session_info_system(),
2261                                            p->msg_ctx,
2262                                            r->in.architecture,
2263                                            r->in.driver, 3, &info_win2k);
2264                 if (W_ERROR_IS_OK(status)) {
2265
2266                         if (delete_files &&
2267                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2268                             printer_driver_files_in_use(info,
2269                                                         get_session_info_system(),
2270                                                         p->msg_ctx,
2271                                                         info_win2k)) {
2272                                 /* no idea of the correct error here */
2273                                 talloc_free(info_win2k);
2274                                 status = WERR_ACCESS_DENIED;
2275                                 goto done;
2276                         }
2277
2278                         /* if we get to here, we now have 2 driver info structures to remove */
2279                         /* remove the Win2k driver first*/
2280
2281                         status = winreg_del_driver(info,
2282                                                    get_session_info_system(),
2283                                                    p->msg_ctx,
2284                                                    info_win2k,
2285                                                    3);
2286
2287                         /* this should not have failed---if it did, report to client */
2288
2289                         if (!W_ERROR_IS_OK(status)) {
2290                                 goto done;
2291                         }
2292
2293                         /*
2294                          * now delete any associated files if delete_files is
2295                          * true. Even if this part failes, we return succes
2296                          * because the driver doesn not exist any more
2297                          */
2298                         if (delete_files) {
2299                                 delete_driver_files(get_session_info_system(),
2300                                                     info_win2k);
2301                         }
2302                 }
2303         }
2304
2305         status = winreg_del_driver(info,
2306                                    get_session_info_system(),
2307                                    p->msg_ctx,
2308                                    info,
2309                                    version);
2310         if (!W_ERROR_IS_OK(status)) {
2311                 goto done;
2312         }
2313
2314         /*
2315          * now delete any associated files if delete_files is
2316          * true. Even if this part failes, we return succes
2317          * because the driver doesn not exist any more
2318          */
2319         if (delete_files) {
2320                 delete_driver_files(get_session_info_system(), info);
2321         }
2322
2323 done:
2324         talloc_free(info);
2325         return status;
2326 }
2327
2328
2329 /********************************************************************
2330  GetPrinterData on a printer server Handle.
2331 ********************************************************************/
2332
2333 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2334                                             const char *value,
2335                                             enum winreg_Type *type,
2336                                             union spoolss_PrinterData *data)
2337 {
2338         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2339
2340         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2341                 *type = REG_DWORD;
2342                 data->value = 0x00;
2343                 return WERR_OK;
2344         }
2345
2346         if (!StrCaseCmp(value, "BeepEnabled")) {
2347                 *type = REG_DWORD;
2348                 data->value = 0x00;
2349                 return WERR_OK;
2350         }
2351
2352         if (!StrCaseCmp(value, "EventLog")) {
2353                 *type = REG_DWORD;
2354                 /* formally was 0x1b */
2355                 data->value = 0x00;
2356                 return WERR_OK;
2357         }
2358
2359         if (!StrCaseCmp(value, "NetPopup")) {
2360                 *type = REG_DWORD;
2361                 data->value = 0x00;
2362                 return WERR_OK;
2363         }
2364
2365         if (!StrCaseCmp(value, "MajorVersion")) {
2366                 *type = REG_DWORD;
2367
2368                 /* Windows NT 4.0 seems to not allow uploading of drivers
2369                    to a server that reports 0x3 as the MajorVersion.
2370                    need to investigate more how Win2k gets around this .
2371                    -- jerry */
2372
2373                 if (RA_WINNT == get_remote_arch()) {
2374                         data->value = 0x02;
2375                 } else {
2376                         data->value = 0x03;
2377                 }
2378
2379                 return WERR_OK;
2380         }
2381
2382         if (!StrCaseCmp(value, "MinorVersion")) {
2383                 *type = REG_DWORD;
2384                 data->value = 0x00;
2385                 return WERR_OK;
2386         }
2387
2388         /* REG_BINARY
2389          *  uint32_t size        = 0x114
2390          *  uint32_t major       = 5
2391          *  uint32_t minor       = [0|1]
2392          *  uint32_t build       = [2195|2600]
2393          *  extra unicode string = e.g. "Service Pack 3"
2394          */
2395         if (!StrCaseCmp(value, "OSVersion")) {
2396                 DATA_BLOB blob;
2397                 enum ndr_err_code ndr_err;
2398                 struct spoolss_OSVersion os;
2399
2400                 os.major                = 5;    /* Windows 2000 == 5.0 */
2401                 os.minor                = 0;
2402                 os.build                = 2195; /* build */
2403                 os.extra_string         = "";   /* leave extra string empty */
2404
2405                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2406                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2407                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2408                         return WERR_GENERAL_FAILURE;
2409                 }
2410
2411                 *type = REG_BINARY;
2412                 data->binary = blob;
2413
2414                 return WERR_OK;
2415         }
2416
2417
2418         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2419                 *type = REG_SZ;
2420
2421                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2422                 W_ERROR_HAVE_NO_MEMORY(data->string);
2423
2424                 return WERR_OK;
2425         }
2426
2427         if (!StrCaseCmp(value, "Architecture")) {
2428                 *type = REG_SZ;
2429                 data->string = talloc_strdup(mem_ctx,
2430                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2431                 W_ERROR_HAVE_NO_MEMORY(data->string);
2432
2433                 return WERR_OK;
2434         }
2435
2436         if (!StrCaseCmp(value, "DsPresent")) {
2437                 *type = REG_DWORD;
2438
2439                 /* only show the publish check box if we are a
2440                    member of a AD domain */
2441
2442                 if (lp_security() == SEC_ADS) {
2443                         data->value = 0x01;
2444                 } else {
2445                         data->value = 0x00;
2446                 }
2447                 return WERR_OK;
2448         }
2449
2450         if (!StrCaseCmp(value, "DNSMachineName")) {
2451                 const char *hostname = get_mydnsfullname();
2452
2453                 if (!hostname) {
2454                         return WERR_BADFILE;
2455                 }
2456
2457                 *type = REG_SZ;
2458                 data->string = talloc_strdup(mem_ctx, hostname);
2459                 W_ERROR_HAVE_NO_MEMORY(data->string);
2460
2461                 return WERR_OK;
2462         }
2463
2464         *type = REG_NONE;
2465
2466         return WERR_INVALID_PARAM;
2467 }
2468
2469 /****************************************************************
2470  _spoolss_GetPrinterData
2471 ****************************************************************/
2472
2473 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2474                                struct spoolss_GetPrinterData *r)
2475 {
2476         struct spoolss_GetPrinterDataEx r2;
2477
2478         r2.in.handle            = r->in.handle;
2479         r2.in.key_name          = "PrinterDriverData";
2480         r2.in.value_name        = r->in.value_name;
2481         r2.in.offered           = r->in.offered;
2482         r2.out.type             = r->out.type;
2483         r2.out.data             = r->out.data;
2484         r2.out.needed           = r->out.needed;
2485
2486         return _spoolss_GetPrinterDataEx(p, &r2);
2487 }
2488
2489 /*********************************************************
2490  Connect to the client machine.
2491 **********************************************************/
2492
2493 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2494                         struct sockaddr_storage *client_ss, const char *remote_machine)
2495 {
2496         NTSTATUS ret;
2497         struct cli_state *the_cli;
2498         struct sockaddr_storage rm_addr;
2499         char addr[INET6_ADDRSTRLEN];
2500
2501         if ( is_zero_addr(client_ss) ) {
2502                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2503                         remote_machine));
2504                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2505                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2506                         return false;
2507                 }
2508                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2509         } else {
2510                 rm_addr = *client_ss;
2511                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2512                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2513                         addr));
2514         }
2515
2516         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2517                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2518                         addr));
2519                 return false;
2520         }
2521
2522         /* setup the connection */
2523         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2524                 &rm_addr, 0, "IPC$", "IPC",
2525                 "", /* username */
2526                 "", /* domain */
2527                 "", /* password */
2528                 0, lp_client_signing());
2529
2530         if ( !NT_STATUS_IS_OK( ret ) ) {
2531                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2532                         remote_machine ));
2533                 return false;
2534         }
2535
2536         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2537                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2538                 cli_shutdown(the_cli);
2539                 return false;
2540         }
2541
2542         /*
2543          * Ok - we have an anonymous connection to the IPC$ share.
2544          * Now start the NT Domain stuff :-).
2545          */
2546
2547         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2548         if (!NT_STATUS_IS_OK(ret)) {
2549                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2550                         remote_machine, nt_errstr(ret)));
2551                 cli_shutdown(the_cli);
2552                 return false;
2553         }
2554
2555         return true;
2556 }
2557
2558 /***************************************************************************
2559  Connect to the client.
2560 ****************************************************************************/
2561
2562 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2563                                         uint32_t localprinter,
2564                                         enum winreg_Type type,
2565                                         struct policy_handle *handle,
2566                                         struct notify_back_channel **_chan,
2567                                         struct sockaddr_storage *client_ss,
2568                                         struct messaging_context *msg_ctx)
2569 {
2570         WERROR result;
2571         NTSTATUS status;
2572         struct notify_back_channel *chan;
2573
2574         for (chan = back_channels; chan; chan = chan->next) {
2575                 if (memcmp(&chan->client_address, client_ss,
2576                            sizeof(struct sockaddr_storage)) == 0) {
2577                         break;
2578                 }
2579         }
2580
2581         /*
2582          * If it's the first connection, contact the client
2583          * and connect to the IPC$ share anonymously
2584          */
2585         if (!chan) {
2586                 fstring unix_printer;
2587
2588                 /* the +2 is to strip the leading 2 backslashs */
2589                 fstrcpy(unix_printer, printer + 2);
2590
2591                 chan = talloc_zero(back_channels, struct notify_back_channel);
2592                 if (!chan) {
2593                         return false;
2594                 }
2595                 chan->client_address = *client_ss;
2596
2597                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2598                         TALLOC_FREE(chan);
2599                         return false;
2600                 }
2601                 chan->binding_handle = chan->cli_pipe->binding_handle;
2602
2603                 DLIST_ADD(back_channels, chan);
2604
2605                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2606                                    receive_notify2_message_list);
2607                 /* Tell the connections db we're now interested in printer
2608                  * notify messages. */
2609                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2610                                             true, FLAG_MSG_PRINT_NOTIFY);
2611         }
2612
2613         /*
2614          * Tell the specific printing tdb we want messages for this printer
2615          * by registering our PID.
2616          */
2617
2618         if (!print_notify_register_pid(snum)) {
2619                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2620                           printer));
2621         }
2622
2623         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2624                                                  talloc_tos(),
2625                                                  printer,
2626                                                  localprinter,
2627                                                  type,
2628                                                  0,
2629                                                  NULL,
2630                                                  handle,
2631                                                  &result);
2632         if (!NT_STATUS_IS_OK(status)) {
2633                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2634                 result = ntstatus_to_werror(status);
2635         } else if (!W_ERROR_IS_OK(result)) {
2636                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2637         }
2638
2639         chan->active_connections++;
2640         *_chan = chan;
2641
2642         return (W_ERROR_IS_OK(result));
2643 }
2644
2645 /****************************************************************
2646  ****************************************************************/
2647
2648 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2649                                                              const struct spoolss_NotifyOption *r)
2650 {
2651         struct spoolss_NotifyOption *option;
2652         uint32_t i,k;
2653
2654         if (!r) {
2655                 return NULL;
2656         }
2657
2658         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2659         if (!option) {
2660                 return NULL;
2661         }
2662
2663         *option = *r;
2664
2665         if (!option->count) {
2666                 return option;
2667         }
2668
2669         option->types = talloc_zero_array(option,
2670                 struct spoolss_NotifyOptionType, option->count);
2671         if (!option->types) {
2672                 talloc_free(option);
2673                 return NULL;
2674         }
2675
2676         for (i=0; i < option->count; i++) {
2677                 option->types[i] = r->types[i];
2678
2679                 if (option->types[i].count) {
2680                         option->types[i].fields = talloc_zero_array(option,
2681                                 union spoolss_Field, option->types[i].count);
2682                         if (!option->types[i].fields) {
2683                                 talloc_free(option);
2684                                 return NULL;
2685                         }
2686                         for (k=0; k<option->types[i].count; k++) {
2687                                 option->types[i].fields[k] =
2688                                         r->types[i].fields[k];
2689                         }
2690                 }
2691         }
2692
2693         return option;
2694 }
2695
2696 /****************************************************************
2697  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2698  *
2699  * before replying OK: status=0 a rpc call is made to the workstation
2700  * asking ReplyOpenPrinter
2701  *
2702  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2703  * called from api_spoolss_rffpcnex
2704 ****************************************************************/
2705
2706 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2707                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2708 {
2709         int snum = -1;
2710         struct spoolss_NotifyOption *option = r->in.notify_options;
2711         struct sockaddr_storage client_ss;
2712
2713         /* store the notify value in the printer struct */
2714
2715         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2716
2717         if (!Printer) {
2718                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2719                         "Invalid handle (%s:%u:%u).\n",
2720                         OUR_HANDLE(r->in.handle)));
2721                 return WERR_BADFID;
2722         }
2723
2724         Printer->notify.flags           = r->in.flags;
2725         Printer->notify.options         = r->in.options;
2726         Printer->notify.printerlocal    = r->in.printer_local;
2727         Printer->notify.msg_ctx         = p->msg_ctx;
2728
2729         TALLOC_FREE(Printer->notify.option);
2730         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2731
2732         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2733
2734         /* Connect to the client machine and send a ReplyOpenPrinter */
2735
2736         if ( Printer->printer_type == SPLHND_SERVER)
2737                 snum = -1;
2738         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2739                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2740                 return WERR_BADFID;
2741
2742         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2743                 "client_address is %s\n", p->client_id->addr));
2744
2745         if (!lp_print_notify_backchannel(snum)) {
2746                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2747                         "backchannel disabled\n"));
2748                 return WERR_SERVER_UNAVAILABLE;
2749         }
2750
2751         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2752                                    AI_NUMERICHOST)) {
2753                 return WERR_SERVER_UNAVAILABLE;
2754         }
2755
2756         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2757                                         Printer->notify.printerlocal, REG_SZ,
2758                                         &Printer->notify.cli_hnd,
2759                                         &Printer->notify.cli_chan,
2760                                         &client_ss, p->msg_ctx)) {
2761                 return WERR_SERVER_UNAVAILABLE;
2762         }
2763
2764         return WERR_OK;
2765 }
2766
2767 /*******************************************************************
2768  * fill a notify_info_data with the servername
2769  ********************************************************************/
2770
2771 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2772                                        int snum,
2773                                        struct spoolss_Notify *data,
2774                                        print_queue_struct *queue,
2775                                        struct spoolss_PrinterInfo2 *pinfo2,
2776                                        TALLOC_CTX *mem_ctx)
2777 {
2778         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2779 }
2780
2781 /*******************************************************************
2782  * fill a notify_info_data with the printername (not including the servername).
2783  ********************************************************************/
2784
2785 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2786                                         int snum,
2787                                         struct spoolss_Notify *data,
2788                                         print_queue_struct *queue,
2789                                         struct spoolss_PrinterInfo2 *pinfo2,
2790                                         TALLOC_CTX *mem_ctx)
2791 {
2792         /* the notify name should not contain the \\server\ part */
2793         const char *p = strrchr(pinfo2->printername, '\\');
2794
2795         if (!p) {
2796                 p = pinfo2->printername;
2797         } else {
2798                 p++;
2799         }
2800
2801         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2802 }
2803
2804 /*******************************************************************
2805  * fill a notify_info_data with the servicename
2806  ********************************************************************/
2807
2808 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2809                                       int snum,
2810                                       struct spoolss_Notify *data,
2811                                       print_queue_struct *queue,
2812                                       struct spoolss_PrinterInfo2 *pinfo2,
2813                                       TALLOC_CTX *mem_ctx)
2814 {
2815         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2816 }
2817
2818 /*******************************************************************
2819  * fill a notify_info_data with the port name
2820  ********************************************************************/
2821
2822 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2823                                      int snum,
2824                                      struct spoolss_Notify *data,
2825                                      print_queue_struct *queue,
2826                                      struct spoolss_PrinterInfo2 *pinfo2,
2827                                      TALLOC_CTX *mem_ctx)
2828 {
2829         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2830 }
2831
2832 /*******************************************************************
2833  * fill a notify_info_data with the printername
2834  * but it doesn't exist, have to see what to do
2835  ********************************************************************/
2836
2837 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2838                                        int snum,
2839                                        struct spoolss_Notify *data,
2840                                        print_queue_struct *queue,
2841                                        struct spoolss_PrinterInfo2 *pinfo2,
2842                                        TALLOC_CTX *mem_ctx)
2843 {
2844         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2845 }
2846
2847 /*******************************************************************
2848  * fill a notify_info_data with the comment
2849  ********************************************************************/
2850
2851 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2852                                    int snum,
2853                                    struct spoolss_Notify *data,
2854                                    print_queue_struct *queue,
2855                                    struct spoolss_PrinterInfo2 *pinfo2,
2856                                    TALLOC_CTX *mem_ctx)
2857 {
2858         const char *p;
2859
2860         if (*pinfo2->comment == '\0') {
2861                 p = lp_comment(snum);
2862         } else {
2863                 p = pinfo2->comment;
2864         }
2865
2866         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2867 }
2868
2869 /*******************************************************************
2870  * fill a notify_info_data with the comment
2871  * location = "Room 1, floor 2, building 3"
2872  ********************************************************************/
2873
2874 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2875                                     int snum,
2876                                     struct spoolss_Notify *data,
2877                                     print_queue_struct *queue,
2878                                     struct spoolss_PrinterInfo2 *pinfo2,
2879                                     TALLOC_CTX *mem_ctx)
2880 {
2881         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2882 }
2883
2884 /*******************************************************************
2885  * fill a notify_info_data with the device mode
2886  * jfm:xxxx don't to it for know but that's a real problem !!!
2887  ********************************************************************/
2888
2889 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2890                                    int snum,
2891                                    struct spoolss_Notify *data,
2892                                    print_queue_struct *queue,
2893                                    struct spoolss_PrinterInfo2 *pinfo2,
2894                                    TALLOC_CTX *mem_ctx)
2895 {
2896         /* for a dummy implementation we have to zero the fields */
2897         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2898 }
2899
2900 /*******************************************************************
2901  * fill a notify_info_data with the separator file name
2902  ********************************************************************/
2903
2904 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2905                                    int snum,
2906                                    struct spoolss_Notify *data,
2907                                    print_queue_struct *queue,
2908                                    struct spoolss_PrinterInfo2 *pinfo2,
2909                                    TALLOC_CTX *mem_ctx)
2910 {
2911         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2912 }
2913
2914 /*******************************************************************
2915  * fill a notify_info_data with the print processor
2916  * jfm:xxxx return always winprint to indicate we don't do anything to it
2917  ********************************************************************/
2918
2919 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2920                                            int snum,
2921                                            struct spoolss_Notify *data,
2922                                            print_queue_struct *queue,
2923                                            struct spoolss_PrinterInfo2 *pinfo2,
2924                                            TALLOC_CTX *mem_ctx)
2925 {
2926         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2927 }
2928
2929 /*******************************************************************
2930  * fill a notify_info_data with the print processor options
2931  * jfm:xxxx send an empty string
2932  ********************************************************************/
2933
2934 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2935                                       int snum,
2936                                       struct spoolss_Notify *data,
2937                                       print_queue_struct *queue,
2938                                       struct spoolss_PrinterInfo2 *pinfo2,
2939                                       TALLOC_CTX *mem_ctx)
2940 {
2941         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the data type
2946  * jfm:xxxx always send RAW as data type
2947  ********************************************************************/
2948
2949 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2950                                     int snum,
2951                                     struct spoolss_Notify *data,
2952                                     print_queue_struct *queue,
2953                                     struct spoolss_PrinterInfo2 *pinfo2,
2954                                     TALLOC_CTX *mem_ctx)
2955 {
2956         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2957 }
2958
2959 /*******************************************************************
2960  * fill a notify_info_data with the security descriptor
2961  * jfm:xxxx send an null pointer to say no security desc
2962  * have to implement security before !
2963  ********************************************************************/
2964
2965 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2966                                          int snum,
2967                                          struct spoolss_Notify *data,
2968                                          print_queue_struct *queue,
2969                                          struct spoolss_PrinterInfo2 *pinfo2,
2970                                          TALLOC_CTX *mem_ctx)
2971 {
2972         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2973 }
2974
2975 /*******************************************************************
2976  * fill a notify_info_data with the attributes
2977  * jfm:xxxx a samba printer is always shared
2978  ********************************************************************/
2979
2980 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2981                                       int snum,
2982                                       struct spoolss_Notify *data,
2983                                       print_queue_struct *queue,
2984                                       struct spoolss_PrinterInfo2 *pinfo2,
2985                                       TALLOC_CTX *mem_ctx)
2986 {
2987         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2988 }
2989
2990 /*******************************************************************
2991  * fill a notify_info_data with the priority
2992  ********************************************************************/
2993
2994 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2995                                     int snum,
2996                                     struct spoolss_Notify *data,
2997                                     print_queue_struct *queue,
2998                                     struct spoolss_PrinterInfo2 *pinfo2,
2999                                     TALLOC_CTX *mem_ctx)
3000 {
3001         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the default priority
3006  ********************************************************************/
3007
3008 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3009                                             int snum,
3010                                             struct spoolss_Notify *data,
3011                                             print_queue_struct *queue,
3012                                             struct spoolss_PrinterInfo2 *pinfo2,
3013                                             TALLOC_CTX *mem_ctx)
3014 {
3015         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3016 }
3017
3018 /*******************************************************************
3019  * fill a notify_info_data with the start time
3020  ********************************************************************/
3021
3022 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3023                                       int snum,
3024                                       struct spoolss_Notify *data,
3025                                       print_queue_struct *queue,
3026                                       struct spoolss_PrinterInfo2 *pinfo2,
3027                                       TALLOC_CTX *mem_ctx)
3028 {
3029         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3030 }
3031
3032 /*******************************************************************
3033  * fill a notify_info_data with the until time
3034  ********************************************************************/
3035
3036 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3037                                       int snum,
3038                                       struct spoolss_Notify *data,
3039                                       print_queue_struct *queue,
3040                                       struct spoolss_PrinterInfo2 *pinfo2,
3041                                       TALLOC_CTX *mem_ctx)
3042 {
3043         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3044 }
3045
3046 /*******************************************************************
3047  * fill a notify_info_data with the status
3048  ********************************************************************/
3049
3050 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3051                                   int snum,
3052                                   struct spoolss_Notify *data,
3053                                   print_queue_struct *queue,
3054                                   struct spoolss_PrinterInfo2 *pinfo2,
3055                                   TALLOC_CTX *mem_ctx)
3056 {
3057         print_status_struct status;
3058
3059         print_queue_length(msg_ctx, snum, &status);
3060         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with the number of jobs queued
3065  ********************************************************************/
3066
3067 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3068                                  int snum,
3069                                  struct spoolss_Notify *data,
3070                                  print_queue_struct *queue,
3071                                  struct spoolss_PrinterInfo2 *pinfo2,
3072                                  TALLOC_CTX *mem_ctx)
3073 {
3074         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3075                 data, print_queue_length(msg_ctx, snum, NULL));
3076 }
3077
3078 /*******************************************************************
3079  * fill a notify_info_data with the average ppm
3080  ********************************************************************/
3081
3082 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3083                                        int snum,
3084                                        struct spoolss_Notify *data,
3085                                        print_queue_struct *queue,
3086                                        struct spoolss_PrinterInfo2 *pinfo2,
3087                                        TALLOC_CTX *mem_ctx)
3088 {
3089         /* always respond 8 pages per minutes */
3090         /* a little hard ! */
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with username
3096  ********************************************************************/
3097
3098 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3099                                     int snum,
3100                                     struct spoolss_Notify *data,
3101                                     print_queue_struct *queue,
3102                                     struct spoolss_PrinterInfo2 *pinfo2,
3103                                     TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with job status
3110  ********************************************************************/
3111
3112 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3113                                       int snum,
3114                                       struct spoolss_Notify *data,
3115                                       print_queue_struct *queue,
3116                                       struct spoolss_PrinterInfo2 *pinfo2,
3117                                       TALLOC_CTX *mem_ctx)
3118 {
3119         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3120 }
3121
3122 /*******************************************************************
3123  * fill a notify_info_data with job name
3124  ********************************************************************/
3125
3126 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3127                                     int snum,
3128                                     struct spoolss_Notify *data,
3129                                     print_queue_struct *queue,
3130                                     struct spoolss_PrinterInfo2 *pinfo2,
3131                                     TALLOC_CTX *mem_ctx)
3132 {
3133         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3134 }
3135
3136 /*******************************************************************
3137  * fill a notify_info_data with job status
3138  ********************************************************************/
3139
3140 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3141                                              int snum,
3142                                              struct spoolss_Notify *data,
3143                                              print_queue_struct *queue,
3144                                              struct spoolss_PrinterInfo2 *pinfo2,
3145                                              TALLOC_CTX *mem_ctx)
3146 {
3147         /*
3148          * Now we're returning job status codes we just return a "" here. JRA.
3149          */
3150
3151         const char *p = "";
3152
3153 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3154         p = "unknown";
3155
3156         switch (queue->status) {
3157         case LPQ_QUEUED:
3158                 p = "Queued";
3159                 break;
3160         case LPQ_PAUSED:
3161                 p = "";    /* NT provides the paused string */
3162                 break;
3163         case LPQ_SPOOLING:
3164                 p = "Spooling";
3165                 break;
3166         case LPQ_PRINTING:
3167                 p = "Printing";
3168                 break;
3169         }
3170 #endif /* NO LONGER NEEDED. */
3171
3172         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3173 }
3174
3175 /*******************************************************************
3176  * fill a notify_info_data with job time
3177  ********************************************************************/
3178
3179 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3180                                     int snum,
3181                                     struct spoolss_Notify *data,
3182                                     print_queue_struct *queue,
3183                                     struct spoolss_PrinterInfo2 *pinfo2,
3184                                     TALLOC_CTX *mem_ctx)
3185 {
3186         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3187 }
3188
3189 /*******************************************************************
3190  * fill a notify_info_data with job size
3191  ********************************************************************/
3192
3193 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3194                                     int snum,
3195                                     struct spoolss_Notify *data,
3196                                     print_queue_struct *queue,
3197                                     struct spoolss_PrinterInfo2 *pinfo2,
3198                                     TALLOC_CTX *mem_ctx)
3199 {
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3201 }
3202
3203 /*******************************************************************
3204  * fill a notify_info_data with page info
3205  ********************************************************************/
3206 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3207                                        int snum,
3208                                 struct spoolss_Notify *data,
3209                                 print_queue_struct *queue,
3210                                 struct spoolss_PrinterInfo2 *pinfo2,
3211                                 TALLOC_CTX *mem_ctx)
3212 {
3213         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3214 }
3215
3216 /*******************************************************************
3217  * fill a notify_info_data with pages printed info.
3218  ********************************************************************/
3219 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3220                                          int snum,
3221                                 struct spoolss_Notify *data,
3222                                 print_queue_struct *queue,
3223                                 struct spoolss_PrinterInfo2 *pinfo2,
3224                                 TALLOC_CTX *mem_ctx)
3225 {
3226         /* Add code when back-end tracks this */
3227         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3228 }
3229
3230 /*******************************************************************
3231  Fill a notify_info_data with job position.
3232  ********************************************************************/
3233
3234 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3235                                         int snum,
3236                                         struct spoolss_Notify *data,
3237                                         print_queue_struct *queue,
3238                                         struct spoolss_PrinterInfo2 *pinfo2,
3239                                         TALLOC_CTX *mem_ctx)
3240 {
3241         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3242 }
3243
3244 /*******************************************************************
3245  Fill a notify_info_data with submitted time.
3246  ********************************************************************/
3247
3248 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3249                                           int snum,
3250                                           struct spoolss_Notify *data,
3251                                           print_queue_struct *queue,
3252                                           struct spoolss_PrinterInfo2 *pinfo2,
3253                                           TALLOC_CTX *mem_ctx)
3254 {
3255         data->data.string.string = NULL;
3256         data->data.string.size = 0;
3257
3258         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3259                                &data->data.string.string,
3260                                &data->data.string.size);
3261
3262 }
3263
3264 struct s_notify_info_data_table
3265 {
3266         enum spoolss_NotifyType type;
3267         uint16_t field;
3268         const char *name;
3269         enum spoolss_NotifyTable variable_type;
3270         void (*fn) (struct messaging_context *msg_ctx,
3271                     int snum, struct spoolss_Notify *data,
3272                     print_queue_struct *queue,
3273                     struct spoolss_PrinterInfo2 *pinfo2,
3274                     TALLOC_CTX *mem_ctx);
3275 };
3276
3277 /* A table describing the various print notification constants and
3278    whether the notification data is a pointer to a variable sized
3279    buffer, a one value uint32_t or a two value uint32_t. */
3280
3281 static const struct s_notify_info_data_table notify_info_data_table[] =
3282 {
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3332 };
3333
3334 /*******************************************************************
3335  Return the variable_type of info_data structure.
3336 ********************************************************************/
3337
3338 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3339                                                                   uint16_t field)
3340 {
3341         int i=0;
3342
3343         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3344                 if ( (notify_info_data_table[i].type == type) &&
3345                      (notify_info_data_table[i].field == field) ) {
3346                         return notify_info_data_table[i].variable_type;
3347                 }
3348         }
3349
3350         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3351
3352         return (enum spoolss_NotifyTable) 0;
3353 }
3354
3355 /****************************************************************************
3356 ****************************************************************************/
3357
3358 static bool search_notify(enum spoolss_NotifyType type,
3359                           uint16_t field,
3360                           int *value)
3361 {
3362         int i;
3363
3364         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3365                 if (notify_info_data_table[i].type == type &&
3366                     notify_info_data_table[i].field == field &&
3367                     notify_info_data_table[i].fn != NULL) {
3368                         *value = i;
3369                         return true;
3370                 }
3371         }
3372
3373         return false;
3374 }
3375
3376 /****************************************************************************
3377 ****************************************************************************/
3378
3379 static void construct_info_data(struct spoolss_Notify *info_data,
3380                                 enum spoolss_NotifyType type,
3381                                 uint16_t field, int id)
3382 {
3383         info_data->type                 = type;
3384         info_data->field.field          = field;
3385         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3386         info_data->job_id               = id;
3387 }
3388
3389 /*******************************************************************
3390  *
3391  * fill a notify_info struct with info asked
3392  *
3393  ********************************************************************/
3394
3395 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3396                                           struct printer_handle *print_hnd,
3397                                           struct spoolss_NotifyInfo *info,
3398                                           struct spoolss_PrinterInfo2 *pinfo2,
3399                                           int snum,
3400                                           const struct spoolss_NotifyOptionType *option_type,
3401                                           uint32_t id,
3402                                           TALLOC_CTX *mem_ctx)
3403 {
3404         int field_num,j;
3405         enum spoolss_NotifyType type;
3406         uint16_t field;
3407
3408         struct spoolss_Notify *current_data;
3409
3410         type = option_type->type;
3411
3412         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3413                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3414                 option_type->count, lp_servicename(snum)));
3415
3416         for(field_num=0; field_num < option_type->count; field_num++) {
3417                 field = option_type->fields[field_num].field;
3418
3419                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3420
3421                 if (!search_notify(type, field, &j) )
3422                         continue;
3423
3424                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3425                                                       struct spoolss_Notify,
3426                                                       info->count + 1);
3427                 if (info->notifies == NULL) {
3428                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3429                         return false;
3430                 }
3431
3432                 current_data = &info->notifies[info->count];
3433
3434                 construct_info_data(current_data, type, field, id);
3435
3436                 DEBUG(10, ("construct_notify_printer_info: "
3437                            "calling [%s]  snum=%d  printername=[%s])\n",
3438                            notify_info_data_table[j].name, snum,
3439                            pinfo2->printername));
3440
3441                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3442                                              NULL, pinfo2, mem_ctx);
3443
3444                 info->count++;
3445         }
3446
3447         return true;
3448 }
3449
3450 /*******************************************************************
3451  *
3452  * fill a notify_info struct with info asked
3453  *
3454  ********************************************************************/
3455
3456 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3457                                        print_queue_struct *queue,
3458                                        struct spoolss_NotifyInfo *info,
3459                                        struct spoolss_PrinterInfo2 *pinfo2,
3460                                        int snum,
3461                                        const struct spoolss_NotifyOptionType *option_type,
3462                                        uint32_t id,
3463                                        TALLOC_CTX *mem_ctx)
3464 {
3465         int field_num,j;
3466         enum spoolss_NotifyType type;
3467         uint16_t field;
3468         struct spoolss_Notify *current_data;
3469
3470         DEBUG(4,("construct_notify_jobs_info\n"));
3471
3472         type = option_type->type;
3473
3474         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3475                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3476                 option_type->count));
3477
3478         for(field_num=0; field_num<option_type->count; field_num++) {
3479                 field = option_type->fields[field_num].field;
3480
3481                 if (!search_notify(type, field, &j) )
3482                         continue;
3483
3484                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3485                                                       struct spoolss_Notify,
3486                                                       info->count + 1);
3487                 if (info->notifies == NULL) {
3488                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3489                         return false;
3490                 }
3491
3492                 current_data=&(info->notifies[info->count]);
3493
3494                 construct_info_data(current_data, type, field, id);
3495                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3496                                              queue, pinfo2, mem_ctx);
3497                 info->count++;
3498         }
3499
3500         return true;
3501 }
3502
3503 /*
3504  * JFM: The enumeration is not that simple, it's even non obvious.
3505  *
3506  * let's take an example: I want to monitor the PRINTER SERVER for
3507  * the printer's name and the number of jobs currently queued.
3508  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3509  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3510  *
3511  * I have 3 printers on the back of my server.
3512  *
3513  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3514  * structures.
3515  *   Number     Data                    Id
3516  *      1       printer 1 name          1
3517  *      2       printer 1 cjob          1
3518  *      3       printer 2 name          2
3519  *      4       printer 2 cjob          2
3520  *      5       printer 3 name          3
3521  *      6       printer 3 name          3
3522  *
3523  * that's the print server case, the printer case is even worse.
3524  */
3525
3526 /*******************************************************************
3527  *
3528  * enumerate all printers on the printserver
3529  * fill a notify_info struct with info asked
3530  *
3531  ********************************************************************/
3532
3533 static WERROR printserver_notify_info(struct pipes_struct *p,
3534                                       struct policy_handle *hnd,
3535                                       struct spoolss_NotifyInfo *info,
3536                                       TALLOC_CTX *mem_ctx)
3537 {
3538         int snum;
3539         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3540         int n_services=lp_numservices();
3541         int i;
3542         struct spoolss_NotifyOption *option;
3543         struct spoolss_NotifyOptionType option_type;
3544         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3545         WERROR result;
3546
3547         DEBUG(4,("printserver_notify_info\n"));
3548
3549         if (!Printer)
3550                 return WERR_BADFID;
3551
3552         option = Printer->notify.option;
3553
3554         info->version   = 2;
3555         info->notifies  = NULL;
3556         info->count     = 0;
3557
3558         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3559            sending a ffpcn() request first */
3560
3561         if ( !option )
3562                 return WERR_BADFID;
3563
3564         for (i=0; i<option->count; i++) {
3565                 option_type = option->types[i];
3566
3567                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3568                         continue;
3569
3570                 for (snum = 0; snum < n_services; snum++) {
3571                         if (!lp_browseable(snum) ||
3572                             !lp_snum_ok(snum) ||
3573                             !lp_print_ok(snum)) {
3574                                 continue; /* skip */
3575                         }
3576
3577                         /* Maybe we should use the SYSTEM session_info here... */
3578                         result = winreg_get_printer(mem_ctx,
3579                                                     get_session_info_system(),
3580                                                     p->msg_ctx,
3581                                                     lp_servicename(snum),
3582                                                     &pinfo2);
3583                         if (!W_ERROR_IS_OK(result)) {
3584                                 DEBUG(4, ("printserver_notify_info: "
3585                                           "Failed to get printer [%s]\n",
3586                                           lp_servicename(snum)));
3587                                 continue;
3588                         }
3589
3590
3591                         construct_notify_printer_info(p->msg_ctx,
3592                                                       Printer, info,
3593                                                       pinfo2, snum,
3594                                                       &option_type, snum,
3595                                                       mem_ctx);
3596
3597                         TALLOC_FREE(pinfo2);
3598                 }
3599         }
3600
3601 #if 0
3602         /*
3603          * Debugging information, don't delete.
3604          */
3605
3606         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3607         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3608         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3609
3610         for (i=0; i<info->count; i++) {
3611                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3612                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3613                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3614         }
3615 #endif
3616
3617         return WERR_OK;
3618 }
3619
3620 /*******************************************************************
3621  *
3622  * fill a notify_info struct with info asked
3623  *
3624  ********************************************************************/
3625
3626 static WERROR printer_notify_info(struct pipes_struct *p,
3627                                   struct policy_handle *hnd,
3628                                   struct spoolss_NotifyInfo *info,
3629                                   TALLOC_CTX *mem_ctx)
3630 {
3631         int snum;
3632         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3633         int i;
3634         uint32_t id;
3635         struct spoolss_NotifyOption *option;
3636         struct spoolss_NotifyOptionType option_type;
3637         int count,j;
3638         print_queue_struct *queue=NULL;
3639         print_status_struct status;
3640         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3641         WERROR result;
3642
3643         DEBUG(4,("printer_notify_info\n"));
3644
3645         if (!Printer)
3646                 return WERR_BADFID;
3647
3648         option = Printer->notify.option;
3649         id = 0x0;
3650
3651         info->version   = 2;
3652         info->notifies  = NULL;
3653         info->count     = 0;
3654
3655         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3656            sending a ffpcn() request first */
3657
3658         if ( !option )
3659                 return WERR_BADFID;
3660
3661         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3662                 return WERR_BADFID;
3663         }
3664
3665         /* Maybe we should use the SYSTEM session_info here... */
3666         result = winreg_get_printer(mem_ctx,
3667                                     get_session_info_system(),
3668                                     p->msg_ctx,
3669                                     lp_servicename(snum), &pinfo2);
3670         if (!W_ERROR_IS_OK(result)) {
3671                 return WERR_BADFID;
3672         }
3673
3674         for (i=0; i<option->count; i++) {
3675                 option_type = option->types[i];
3676
3677                 switch (option_type.type) {
3678                 case PRINTER_NOTIFY_TYPE:
3679                         if (construct_notify_printer_info(p->msg_ctx,
3680                                                           Printer, info,
3681                                                           pinfo2, snum,
3682                                                           &option_type, id,
3683                                                           mem_ctx)) {
3684                                 id--;
3685                         }
3686                         break;
3687
3688                 case JOB_NOTIFY_TYPE:
3689
3690                         count = print_queue_status(p->msg_ctx, snum, &queue,
3691                                                    &status);
3692
3693                         for (j=0; j<count; j++) {
3694                                 construct_notify_jobs_info(p->msg_ctx,
3695                                                            &queue[j], info,
3696                                                            pinfo2, snum,
3697                                                            &option_type,
3698                                                            queue[j].job,
3699                                                            mem_ctx);
3700                         }
3701
3702                         SAFE_FREE(queue);
3703                         break;
3704                 }
3705         }
3706
3707         /*
3708          * Debugging information, don't delete.
3709          */
3710         /*
3711         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3712         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3713         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714
3715         for (i=0; i<info->count; i++) {
3716                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3717                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3718                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3719         }
3720         */
3721
3722         talloc_free(pinfo2);
3723         return WERR_OK;
3724 }
3725
3726 /****************************************************************
3727  _spoolss_RouterRefreshPrinterChangeNotify
3728 ****************************************************************/
3729
3730 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3731                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3732 {
3733         struct spoolss_NotifyInfo *info;
3734
3735         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3736         WERROR result = WERR_BADFID;
3737
3738         /* we always have a spoolss_NotifyInfo struct */
3739         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3740         if (!info) {
3741                 result = WERR_NOMEM;
3742                 goto done;
3743         }
3744
3745         *r->out.info = info;
3746
3747         if (!Printer) {
3748                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3749                         "Invalid handle (%s:%u:%u).\n",
3750                         OUR_HANDLE(r->in.handle)));
3751                 goto done;
3752         }
3753
3754         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3755
3756         /*
3757          *      We are now using the change value, and
3758          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3759          *      I don't have a global notification system, I'm sending back all the
3760          *      information even when _NOTHING_ has changed.
3761          */
3762
3763         /* We need to keep track of the change value to send back in
3764            RRPCN replies otherwise our updates are ignored. */
3765
3766         Printer->notify.fnpcn = true;
3767
3768         if (Printer->notify.cli_chan != NULL &&
3769             Printer->notify.cli_chan->active_connections > 0) {
3770                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3771                         "Saving change value in request [%x]\n",
3772                         r->in.change_low));
3773                 Printer->notify.change = r->in.change_low;
3774         }
3775
3776         /* just ignore the spoolss_NotifyOption */
3777
3778         switch (Printer->printer_type) {
3779                 case SPLHND_SERVER:
3780                         result = printserver_notify_info(p, r->in.handle,
3781                                                          info, p->mem_ctx);
3782                         break;
3783
3784                 case SPLHND_PRINTER:
3785                         result = printer_notify_info(p, r->in.handle,
3786                                                      info, p->mem_ctx);
3787                         break;
3788         }
3789
3790         Printer->notify.fnpcn = false;
3791
3792 done:
3793         return result;
3794 }
3795
3796 /********************************************************************
3797  ********************************************************************/
3798
3799 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3800                                  const char *servername,
3801                                  const char *printername,
3802                                  const char **printername_p)
3803 {
3804         /* FIXME: add lp_force_printername() */
3805
3806         if (servername == NULL) {
3807                 *printername_p = talloc_strdup(mem_ctx, printername);
3808                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3809                 return WERR_OK;
3810         }
3811
3812         if (servername[0] == '\\' && servername[1] == '\\') {
3813                 servername += 2;
3814         }
3815
3816         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3817         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3818
3819         return WERR_OK;
3820 }
3821
3822 /********************************************************************
3823  ********************************************************************/
3824
3825 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3826                                           const char *printername)
3827 {
3828         if (dm == NULL) {
3829                 return;
3830         }
3831
3832         dm->devicename = talloc_strndup(dm, printername,
3833                                         MIN(strlen(printername), 31));
3834 }
3835
3836 /********************************************************************
3837  * construct_printer_info_0
3838  * fill a printer_info_0 struct
3839  ********************************************************************/
3840
3841 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3842                                       const struct auth_serversupplied_info *session_info,
3843                                       struct messaging_context *msg_ctx,
3844                                       struct spoolss_PrinterInfo2 *info2,
3845                                       const char *servername,
3846                                       struct spoolss_PrinterInfo0 *r,
3847                                       int snum)
3848 {
3849         int count;
3850         struct printer_session_counter *session_counter;
3851         struct timeval setuptime;
3852         print_status_struct status;
3853         WERROR result;
3854
3855         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3856         if (!W_ERROR_IS_OK(result)) {
3857                 return result;
3858         }
3859
3860         if (servername) {
3861                 r->servername = talloc_strdup(mem_ctx, servername);
3862                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3863         } else {
3864                 r->servername = NULL;
3865         }
3866
3867         count = print_queue_length(msg_ctx, snum, &status);
3868
3869         /* check if we already have a counter for this printer */
3870         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3871                 if (session_counter->snum == snum)
3872                         break;
3873         }
3874
3875         /* it's the first time, add it to the list */
3876         if (session_counter == NULL) {
3877                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3878                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3879                 session_counter->snum           = snum;
3880                 session_counter->counter        = 0;
3881                 DLIST_ADD(counter_list, session_counter);
3882         }
3883
3884         /* increment it */
3885         session_counter->counter++;
3886
3887         r->cjobs                        = count;
3888         r->total_jobs                   = 0;
3889         r->total_bytes                  = 0;
3890
3891         get_startup_time(&setuptime);
3892         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3893
3894         /* JFM:
3895          * the global_counter should be stored in a TDB as it's common to all the clients
3896          * and should be zeroed on samba startup
3897          */
3898         r->global_counter               = session_counter->counter;
3899         r->total_pages                  = 0;
3900         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3901         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3902         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3903         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3904         r->spooling                     = 0;
3905         r->max_spooling                 = 0;
3906         r->session_counter              = session_counter->counter;
3907         r->num_error_out_of_paper       = 0x0;
3908         r->num_error_not_ready          = 0x0;          /* number of print failure */
3909         r->job_error                    = 0x0;
3910         r->number_of_processors         = 0x1;
3911         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3912         r->high_part_total_bytes        = 0x0;
3913
3914         /* ChangeID in milliseconds*/
3915         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3916                                     info2->sharename, &r->change_id);
3917
3918         r->last_error                   = WERR_OK;
3919         r->status                       = nt_printq_status(status.status);
3920         r->enumerate_network_printers   = 0x0;
3921         r->c_setprinter                 = 0x0;
3922         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3923         r->processor_level              = 0x6;          /* 6  ???*/
3924         r->ref_ic                       = 0;
3925         r->reserved2                    = 0;
3926         r->reserved3                    = 0;
3927
3928         return WERR_OK;
3929 }
3930
3931
3932 /********************************************************************
3933  * construct_printer_info1
3934  * fill a spoolss_PrinterInfo1 struct
3935 ********************************************************************/
3936
3937 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3938                                       const struct spoolss_PrinterInfo2 *info2,
3939                                       uint32_t flags,
3940                                       const char *servername,
3941                                       struct spoolss_PrinterInfo1 *r,
3942                                       int snum)
3943 {
3944         WERROR result;
3945
3946         r->flags                = flags;
3947
3948         if (info2->comment == NULL || info2->comment[0] == '\0') {
3949                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3950         } else {
3951                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3952         }
3953         W_ERROR_HAVE_NO_MEMORY(r->comment);
3954
3955         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3956         if (!W_ERROR_IS_OK(result)) {
3957                 return result;
3958         }
3959
3960         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3961                                                   r->name,
3962                                                   info2->drivername,
3963                                                   r->comment);
3964         W_ERROR_HAVE_NO_MEMORY(r->description);
3965
3966         return WERR_OK;
3967 }
3968
3969 /********************************************************************
3970  * construct_printer_info2
3971  * fill a spoolss_PrinterInfo2 struct
3972 ********************************************************************/
3973
3974 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3975                                       struct messaging_context *msg_ctx,
3976                                       const struct spoolss_PrinterInfo2 *info2,
3977                                       const char *servername,
3978                                       struct spoolss_PrinterInfo2 *r,
3979                                       int snum)
3980 {
3981         int count;
3982         print_status_struct status;
3983         WERROR result;
3984
3985         count = print_queue_length(msg_ctx, snum, &status);
3986
3987         if (servername) {
3988                 r->servername           = talloc_strdup(mem_ctx, servername);
3989                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3990         } else {
3991                 r->servername           = NULL;
3992         }
3993
3994         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3995         if (!W_ERROR_IS_OK(result)) {
3996                 return result;
3997         }
3998
3999         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4000         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4001         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4002         W_ERROR_HAVE_NO_MEMORY(r->portname);
4003         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4004         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4005
4006         if (info2->comment[0] == '\0') {
4007                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4008         } else {
4009                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4010         }
4011         W_ERROR_HAVE_NO_MEMORY(r->comment);
4012
4013         r->location             = talloc_strdup(mem_ctx, info2->location);
4014         W_ERROR_HAVE_NO_MEMORY(r->location);
4015         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4016         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4017         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4018         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4019         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4020         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4021         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4022         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4023
4024         r->attributes           = info2->attributes;
4025
4026         r->priority             = info2->priority;
4027         r->defaultpriority      = info2->defaultpriority;
4028         r->starttime            = info2->starttime;
4029         r->untiltime            = info2->untiltime;
4030         r->status               = nt_printq_status(status.status);
4031         r->cjobs                = count;
4032         r->averageppm           = info2->averageppm;
4033
4034         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4035         if (!r->devmode) {
4036                 DEBUG(8,("Returning NULL Devicemode!\n"));
4037         }
4038
4039         compose_devicemode_devicename(r->devmode, r->printername);
4040
4041         r->secdesc = NULL;
4042
4043         if (info2->secdesc != NULL) {
4044                 /* don't use talloc_steal() here unless you do a deep steal of all
4045                    the SEC_DESC members */
4046
4047                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4048         }
4049
4050         return WERR_OK;
4051 }
4052
4053 /********************************************************************
4054  * construct_printer_info3
4055  * fill a spoolss_PrinterInfo3 struct
4056  ********************************************************************/
4057
4058 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4059                                       const struct spoolss_PrinterInfo2 *info2,
4060                                       const char *servername,
4061                                       struct spoolss_PrinterInfo3 *r,
4062                                       int snum)
4063 {
4064         /* These are the components of the SD we are returning. */
4065
4066         if (info2->secdesc != NULL) {
4067                 /* don't use talloc_steal() here unless you do a deep steal of all
4068                    the SEC_DESC members */
4069
4070                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4071                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4072         }
4073
4074         return WERR_OK;
4075 }
4076
4077 /********************************************************************
4078  * construct_printer_info4
4079  * fill a spoolss_PrinterInfo4 struct
4080  ********************************************************************/
4081
4082 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4083                                       const struct spoolss_PrinterInfo2 *info2,
4084                                       const char *servername,
4085                                       struct spoolss_PrinterInfo4 *r,
4086                                       int snum)
4087 {
4088         WERROR result;
4089
4090         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4091         if (!W_ERROR_IS_OK(result)) {
4092                 return result;
4093         }
4094
4095         if (servername) {
4096                 r->servername   = talloc_strdup(mem_ctx, servername);
4097                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4098         } else {
4099                 r->servername = NULL;
4100         }
4101
4102         r->attributes   = info2->attributes;
4103
4104         return WERR_OK;
4105 }
4106
4107 /********************************************************************
4108  * construct_printer_info5
4109  * fill a spoolss_PrinterInfo5 struct
4110  ********************************************************************/
4111
4112 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4113                                       const struct spoolss_PrinterInfo2 *info2,
4114                                       const char *servername,
4115                                       struct spoolss_PrinterInfo5 *r,
4116                                       int snum)
4117 {
4118         WERROR result;
4119
4120         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4121         if (!W_ERROR_IS_OK(result)) {
4122                 return result;
4123         }
4124
4125         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4126         W_ERROR_HAVE_NO_MEMORY(r->portname);
4127
4128         r->attributes   = info2->attributes;
4129
4130         /* these two are not used by NT+ according to MSDN */
4131         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4132         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4133
4134         return WERR_OK;
4135 }
4136
4137 /********************************************************************
4138  * construct_printer_info_6
4139  * fill a spoolss_PrinterInfo6 struct
4140  ********************************************************************/
4141
4142 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4143                                       struct messaging_context *msg_ctx,
4144                                       const struct spoolss_PrinterInfo2 *info2,
4145                                       const char *servername,
4146                                       struct spoolss_PrinterInfo6 *r,
4147                                       int snum)
4148 {
4149         int count;
4150         print_status_struct status;
4151
4152         count = print_queue_length(msg_ctx, snum, &status);
4153
4154         r->status = nt_printq_status(status.status);
4155
4156         return WERR_OK;
4157 }
4158
4159 /********************************************************************
4160  * construct_printer_info7
4161  * fill a spoolss_PrinterInfo7 struct
4162  ********************************************************************/
4163
4164 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4165                                       struct messaging_context *msg_ctx,
4166                                       const char *servername,
4167                                       struct spoolss_PrinterInfo7 *r,
4168                                       int snum)
4169 {
4170         struct auth_serversupplied_info *session_info;
4171         struct GUID guid;
4172         NTSTATUS status;
4173
4174         status = make_session_info_system(mem_ctx, &session_info);
4175         if (!NT_STATUS_IS_OK(status)) {
4176                 DEBUG(0, ("construct_printer_info7: "
4177                           "Could not create system session_info\n"));
4178                 return WERR_NOMEM;
4179         }
4180
4181         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4182                                  servername,
4183                                  lp_servicename(snum), &guid, NULL)) {
4184                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4185                 r->action = DSPRINT_PUBLISH;
4186         } else {
4187                 r->guid = talloc_strdup(mem_ctx, "");
4188                 r->action = DSPRINT_UNPUBLISH;
4189         }
4190         W_ERROR_HAVE_NO_MEMORY(r->guid);
4191
4192         TALLOC_FREE(session_info);
4193         return WERR_OK;
4194 }
4195
4196 /********************************************************************
4197  * construct_printer_info8
4198  * fill a spoolss_PrinterInfo8 struct
4199  ********************************************************************/
4200
4201 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4202                                       const struct spoolss_PrinterInfo2 *info2,
4203                                       const char *servername,
4204                                       struct spoolss_DeviceModeInfo *r,
4205                                       int snum)
4206 {
4207         WERROR result;
4208         const char *printername;
4209
4210         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4211         if (!W_ERROR_IS_OK(result)) {
4212                 return result;
4213         }
4214
4215         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4216         if (!r->devmode) {
4217                 DEBUG(8,("Returning NULL Devicemode!\n"));
4218         }
4219
4220         compose_devicemode_devicename(r->devmode, printername);
4221
4222         return WERR_OK;
4223 }
4224
4225
4226 /********************************************************************
4227 ********************************************************************/
4228
4229 static bool snum_is_shared_printer(int snum)
4230 {
4231         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4232 }
4233
4234 /********************************************************************
4235  Spoolss_enumprinters.
4236 ********************************************************************/
4237
4238 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4239                                            const struct auth_serversupplied_info *session_info,
4240                                            struct messaging_context *msg_ctx,
4241                                            const char *servername,
4242                                            uint32_t level,
4243                                            uint32_t flags,
4244                                            union spoolss_PrinterInfo **info_p,
4245                                            uint32_t *count_p)
4246 {
4247         int snum;
4248         int n_services = lp_numservices();
4249         union spoolss_PrinterInfo *info = NULL;
4250         uint32_t count = 0;
4251         WERROR result = WERR_OK;
4252
4253         *count_p = 0;
4254         *info_p = NULL;
4255
4256         for (snum = 0; snum < n_services; snum++) {
4257
4258                 const char *printer;
4259                 struct spoolss_PrinterInfo2 *info2;
4260
4261                 if (!snum_is_shared_printer(snum)) {
4262                         continue;
4263                 }
4264
4265                 printer = lp_const_servicename(snum);
4266
4267                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4268                         printer, snum));
4269
4270                 result = winreg_create_printer(mem_ctx,
4271                                                session_info,
4272                                                msg_ctx,
4273                                                printer);
4274                 if (!W_ERROR_IS_OK(result)) {
4275                         goto out;
4276                 }
4277
4278                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4279                                             union spoolss_PrinterInfo,
4280                                             count + 1);
4281                 if (!info) {
4282                         result = WERR_NOMEM;
4283                         goto out;
4284                 }
4285
4286                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4287                                             printer, &info2);
4288                 if (!W_ERROR_IS_OK(result)) {
4289                         goto out;
4290                 }
4291
4292                 switch (level) {
4293                 case 0:
4294                         result = construct_printer_info0(info, session_info,
4295                                                          msg_ctx, info2,
4296                                                          servername,
4297                                                          &info[count].info0, snum);
4298                         break;
4299                 case 1:
4300                         result = construct_printer_info1(info, info2, flags,
4301                                                          servername,
4302                                                          &info[count].info1, snum);
4303                         break;
4304                 case 2:
4305                         result = construct_printer_info2(info, msg_ctx, info2,
4306                                                          servername,
4307                                                          &info[count].info2, snum);
4308                         break;
4309                 case 4:
4310                         result = construct_printer_info4(info, info2,
4311                                                          servername,
4312                                                          &info[count].info4, snum);
4313                         break;
4314                 case 5:
4315                         result = construct_printer_info5(info, info2,
4316                                                          servername,
4317                                                          &info[count].info5, snum);
4318                         break;
4319
4320                 default:
4321                         result = WERR_UNKNOWN_LEVEL;
4322                         goto out;
4323                 }
4324
4325                 if (!W_ERROR_IS_OK(result)) {
4326                         goto out;
4327                 }
4328
4329                 count++;
4330         }
4331
4332         *count_p = count;
4333         *info_p = info;
4334
4335  out:
4336         if (!W_ERROR_IS_OK(result)) {
4337                 TALLOC_FREE(info);
4338                 return result;
4339         }
4340
4341         *info_p = info;
4342
4343         return WERR_OK;
4344 }
4345
4346 /********************************************************************
4347  * handle enumeration of printers at level 0
4348  ********************************************************************/
4349
4350 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4351                                   const struct auth_serversupplied_info *session_info,
4352                                   struct messaging_context *msg_ctx,
4353                                   uint32_t flags,
4354                                   const char *servername,
4355                                   union spoolss_PrinterInfo **info,
4356                                   uint32_t *count)
4357 {
4358         DEBUG(4,("enum_all_printers_info_0\n"));
4359
4360         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4361                                             servername, 0, flags, info, count);
4362 }
4363
4364
4365 /********************************************************************
4366 ********************************************************************/
4367
4368 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4369                                        const struct auth_serversupplied_info *session_info,
4370                                        struct messaging_context *msg_ctx,
4371                                        const char *servername,
4372                                        uint32_t flags,
4373                                        union spoolss_PrinterInfo **info,
4374                                        uint32_t *count)
4375 {
4376         DEBUG(4,("enum_all_printers_info_1\n"));
4377
4378         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4379                                             servername, 1, flags, info, count);
4380 }
4381
4382 /********************************************************************
4383  enum_all_printers_info_1_local.
4384 *********************************************************************/
4385
4386 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4387                                              const struct auth_serversupplied_info *session_info,
4388                                              struct messaging_context *msg_ctx,
4389                                              const char *servername,
4390                                              union spoolss_PrinterInfo **info,
4391                                              uint32_t *count)
4392 {
4393         DEBUG(4,("enum_all_printers_info_1_local\n"));
4394
4395         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4396                                         servername, PRINTER_ENUM_ICON8, info, count);
4397 }
4398
4399 /********************************************************************
4400  enum_all_printers_info_1_name.
4401 *********************************************************************/
4402
4403 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4404                                             const struct auth_serversupplied_info *session_info,
4405                                             struct messaging_context *msg_ctx,
4406                                             const char *servername,
4407                                             union spoolss_PrinterInfo **info,
4408                                             uint32_t *count)
4409 {
4410         const char *s = servername;
4411
4412         DEBUG(4,("enum_all_printers_info_1_name\n"));
4413
4414         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4415                 s = servername + 2;
4416         }
4417
4418         if (!is_myname_or_ipaddr(s)) {
4419                 return WERR_INVALID_NAME;
4420         }
4421
4422         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4423                                         servername, PRINTER_ENUM_ICON8, info, count);
4424 }
4425
4426 /********************************************************************
4427  enum_all_printers_info_1_network.
4428 *********************************************************************/
4429
4430 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4431                                                const struct auth_serversupplied_info *session_info,
4432                                                struct messaging_context *msg_ctx,
4433                                                const char *servername,
4434                                                union spoolss_PrinterInfo **info,
4435                                                uint32_t *count)
4436 {
4437         const char *s = servername;
4438
4439         DEBUG(4,("enum_all_printers_info_1_network\n"));
4440
4441         /* If we respond to a enum_printers level 1 on our name with flags
4442            set to PRINTER_ENUM_REMOTE with a list of printers then these
4443            printers incorrectly appear in the APW browse list.
4444            Specifically the printers for the server appear at the workgroup
4445            level where all the other servers in the domain are
4446            listed. Windows responds to this call with a
4447            WERR_CAN_NOT_COMPLETE so we should do the same. */
4448
4449         if (servername[0] == '\\' && servername[1] == '\\') {
4450                  s = servername + 2;
4451         }
4452
4453         if (is_myname_or_ipaddr(s)) {
4454                  return WERR_CAN_NOT_COMPLETE;
4455         }
4456
4457         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4458                                         servername, PRINTER_ENUM_NAME, info, count);
4459 }
4460
4461 /********************************************************************
4462  * api_spoolss_enumprinters
4463  *
4464  * called from api_spoolss_enumprinters (see this to understand)
4465  ********************************************************************/
4466
4467 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4468                                        const struct auth_serversupplied_info *session_info,
4469                                        struct messaging_context *msg_ctx,
4470                                        const char *servername,
4471                                        union spoolss_PrinterInfo **info,
4472                                        uint32_t *count)
4473 {
4474         DEBUG(4,("enum_all_printers_info_2\n"));
4475
4476         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4477                                             servername, 2, 0, info, count);
4478 }
4479
4480 /********************************************************************
4481  * handle enumeration of printers at level 1
4482  ********************************************************************/
4483
4484 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4485                                   const struct auth_serversupplied_info *session_info,
4486                                   struct messaging_context *msg_ctx,
4487                                   uint32_t flags,
4488                                   const char *servername,
4489                                   union spoolss_PrinterInfo **info,
4490                                   uint32_t *count)
4491 {
4492         /* Not all the flags are equals */
4493
4494         if (flags & PRINTER_ENUM_LOCAL) {
4495                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4496                                                       msg_ctx, servername, info, count);
4497         }
4498
4499         if (flags & PRINTER_ENUM_NAME) {
4500                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4501                                                      msg_ctx, servername, info,
4502                                                      count);
4503         }
4504
4505         if (flags & PRINTER_ENUM_NETWORK) {
4506                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4507                                                         msg_ctx, servername, info,
4508                                                         count);
4509         }
4510
4511         return WERR_OK; /* NT4sp5 does that */
4512 }
4513
4514 /********************************************************************
4515  * handle enumeration of printers at level 2
4516  ********************************************************************/
4517
4518 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4519                                   const struct auth_serversupplied_info *session_info,
4520                                   struct messaging_context *msg_ctx,
4521                                   uint32_t flags,
4522                                   const char *servername,
4523                                   union spoolss_PrinterInfo **info,
4524                                   uint32_t *count)
4525 {
4526         if (flags & PRINTER_ENUM_LOCAL) {
4527
4528                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4529                                                 servername,
4530                                                 info, count);
4531         }
4532
4533         if (flags & PRINTER_ENUM_NAME) {
4534                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4535                         return WERR_INVALID_NAME;
4536                 }
4537
4538                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4539                                                 servername,
4540                                                 info, count);
4541         }
4542
4543         if (flags & PRINTER_ENUM_REMOTE) {
4544                 return WERR_UNKNOWN_LEVEL;
4545         }
4546
4547         return WERR_OK;
4548 }
4549
4550 /********************************************************************
4551  * handle enumeration of printers at level 4
4552  ********************************************************************/
4553
4554 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4555                                   const struct auth_serversupplied_info *session_info,
4556                                   struct messaging_context *msg_ctx,
4557                                   uint32_t flags,
4558                                   const char *servername,
4559                                   union spoolss_PrinterInfo **info,
4560                                   uint32_t *count)
4561 {
4562         DEBUG(4,("enum_all_printers_info_4\n"));
4563
4564         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4565                                             servername, 4, flags, info, count);
4566 }
4567
4568
4569 /********************************************************************
4570  * handle enumeration of printers at level 5
4571  ********************************************************************/
4572
4573 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4574                                   const struct auth_serversupplied_info *session_info,
4575                                   struct messaging_context *msg_ctx,
4576                                   uint32_t flags,
4577                                   const char *servername,
4578                                   union spoolss_PrinterInfo **info,
4579                                   uint32_t *count)
4580 {
4581         DEBUG(4,("enum_all_printers_info_5\n"));
4582
4583         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4584                                             servername, 5, flags, info, count);
4585 }
4586
4587 /****************************************************************
4588  _spoolss_EnumPrinters
4589 ****************************************************************/
4590
4591 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4592                              struct spoolss_EnumPrinters *r)
4593 {
4594         const struct auth_serversupplied_info *session_info = get_session_info_system();
4595         WERROR result;
4596
4597         /* that's an [in out] buffer */
4598
4599         if (!r->in.buffer && (r->in.offered != 0)) {
4600                 return WERR_INVALID_PARAM;
4601         }
4602
4603         DEBUG(4,("_spoolss_EnumPrinters\n"));
4604
4605         *r->out.needed = 0;
4606         *r->out.count = 0;
4607         *r->out.info = NULL;
4608
4609         /*
4610          * Level 1:
4611          *          flags==PRINTER_ENUM_NAME
4612          *           if name=="" then enumerates all printers
4613          *           if name!="" then enumerate the printer
4614          *          flags==PRINTER_ENUM_REMOTE
4615          *          name is NULL, enumerate printers
4616          * Level 2: name!="" enumerates printers, name can't be NULL
4617          * Level 3: doesn't exist
4618          * Level 4: does a local registry lookup
4619          * Level 5: same as Level 2
4620          */
4621
4622         if (r->in.server && r->in.server[0] == '\0') {
4623                 r->in.server = NULL;
4624         }
4625
4626         switch (r->in.level) {
4627         case 0:
4628                 result = enumprinters_level0(p->mem_ctx, session_info,
4629                                              p->msg_ctx, r->in.flags,
4630                                              r->in.server,
4631                                              r->out.info, r->out.count);
4632                 break;
4633         case 1:
4634                 result = enumprinters_level1(p->mem_ctx, session_info,
4635                                              p->msg_ctx, r->in.flags,
4636                                              r->in.server,
4637                                              r->out.info, r->out.count);
4638                 break;
4639         case 2:
4640                 result = enumprinters_level2(p->mem_ctx, session_info,
4641                                              p->msg_ctx, r->in.flags,
4642                                              r->in.server,
4643                                              r->out.info, r->out.count);
4644                 break;
4645         case 4:
4646                 result = enumprinters_level4(p->mem_ctx, session_info,
4647                                              p->msg_ctx, r->in.flags,
4648                                              r->in.server,
4649                                              r->out.info, r->out.count);
4650                 break;
4651         case 5:
4652                 result = enumprinters_level5(p->mem_ctx, session_info,
4653                                              p->msg_ctx, r->in.flags,
4654                                              r->in.server,
4655                                              r->out.info, r->out.count);
4656                 break;
4657         default:
4658                 return WERR_UNKNOWN_LEVEL;
4659         }
4660
4661         if (!W_ERROR_IS_OK(result)) {
4662                 return result;
4663         }
4664
4665         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4666                                                      spoolss_EnumPrinters,
4667                                                      *r->out.info, r->in.level,
4668                                                      *r->out.count);
4669         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4670         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4671
4672         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4673 }
4674
4675 /****************************************************************
4676  _spoolss_GetPrinter
4677 ****************************************************************/
4678
4679 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4680                            struct spoolss_GetPrinter *r)
4681 {
4682         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4683         struct spoolss_PrinterInfo2 *info2 = NULL;
4684         WERROR result = WERR_OK;
4685         int snum;
4686
4687         /* that's an [in out] buffer */
4688
4689         if (!r->in.buffer && (r->in.offered != 0)) {
4690                 return WERR_INVALID_PARAM;
4691         }
4692
4693         *r->out.needed = 0;
4694
4695         if (Printer == NULL) {
4696                 return WERR_BADFID;
4697         }
4698
4699         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4700                 return WERR_BADFID;
4701         }
4702
4703         result = winreg_get_printer(p->mem_ctx,
4704                                     get_session_info_system(),
4705                                     p->msg_ctx,
4706                                     lp_const_servicename(snum),
4707                                     &info2);
4708         if (!W_ERROR_IS_OK(result)) {
4709                 goto out;
4710         }
4711
4712         switch (r->in.level) {
4713         case 0:
4714                 result = construct_printer_info0(p->mem_ctx,
4715                                                  get_session_info_system(),
4716                                                  p->msg_ctx,
4717                                                  info2,
4718                                                  Printer->servername,
4719                                                  &r->out.info->info0,
4720                                                  snum);
4721                 break;
4722         case 1:
4723                 result = construct_printer_info1(p->mem_ctx, info2,
4724                                                  PRINTER_ENUM_ICON8,
4725                                                  Printer->servername,
4726                                                  &r->out.info->info1, snum);
4727                 break;
4728         case 2:
4729                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4730                                                  Printer->servername,
4731                                                  &r->out.info->info2, snum);
4732                 break;
4733         case 3:
4734                 result = construct_printer_info3(p->mem_ctx, info2,
4735                                                  Printer->servername,
4736                                                  &r->out.info->info3, snum);
4737                 break;
4738         case 4:
4739                 result = construct_printer_info4(p->mem_ctx, info2,
4740                                                  Printer->servername,
4741                                                  &r->out.info->info4, snum);
4742                 break;
4743         case 5:
4744                 result = construct_printer_info5(p->mem_ctx, info2,
4745                                                  Printer->servername,
4746                                                  &r->out.info->info5, snum);
4747                 break;
4748         case 6:
4749                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4750                                                  Printer->servername,
4751                                                  &r->out.info->info6, snum);
4752                 break;
4753         case 7:
4754                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4755                                                  Printer->servername,
4756                                                  &r->out.info->info7, snum);
4757                 break;
4758         case 8:
4759                 result = construct_printer_info8(p->mem_ctx, info2,
4760                                                  Printer->servername,
4761                                                  &r->out.info->info8, snum);
4762                 break;
4763         default:
4764                 result = WERR_UNKNOWN_LEVEL;
4765                 break;
4766         }
4767
4768  out:
4769         if (!W_ERROR_IS_OK(result)) {
4770                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4771                           r->in.level, win_errstr(result)));
4772                 TALLOC_FREE(r->out.info);
4773                 return result;
4774         }
4775
4776         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4777                                                r->out.info, r->in.level);
4778         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4779
4780         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4781 }
4782
4783 /********************************************************************
4784  ********************************************************************/
4785
4786 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4787         do { \
4788                 if (in && strlen(in)) { \
4789                         out = talloc_strdup(mem_ctx, in); \
4790                 } else { \
4791                         out = talloc_strdup(mem_ctx, ""); \
4792                 } \
4793                 W_ERROR_HAVE_NO_MEMORY(out); \
4794         } while (0);
4795
4796 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4797         do { \
4798                 if (in && strlen(in)) { \
4799                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4800                 } else { \
4801                         out = talloc_strdup(mem_ctx, ""); \
4802                 } \
4803                 W_ERROR_HAVE_NO_MEMORY(out); \
4804         } while (0);
4805
4806 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4807                                                   const char **string_array,
4808                                                   const char ***presult,
4809                                                   const char *cservername,
4810                                                   const char *arch,
4811                                                   int version)
4812 {
4813         int i, num_strings = 0;
4814         const char **array = NULL;
4815
4816         if (string_array == NULL) {
4817                 return WERR_INVALID_PARAMETER;
4818         }
4819
4820         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4821                 const char *str = NULL;
4822
4823                 if (cservername == NULL || arch == NULL) {
4824                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4825                 } else {
4826                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4827                 }
4828
4829                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4830                         TALLOC_FREE(array);
4831                         return WERR_NOMEM;
4832                 }
4833         }
4834
4835         if (i > 0) {
4836                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4837                              &array, &num_strings);
4838         }
4839
4840         if (presult) {
4841                 *presult = array;
4842         }
4843
4844         return WERR_OK;
4845 }
4846
4847 /********************************************************************
4848  * fill a spoolss_DriverInfo1 struct
4849  ********************************************************************/
4850
4851 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4852                                         struct spoolss_DriverInfo1 *r,
4853                                         const struct spoolss_DriverInfo8 *driver,
4854                                         const char *servername)
4855 {
4856         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4857         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4858
4859         return WERR_OK;
4860 }
4861
4862 /********************************************************************
4863  * fill a spoolss_DriverInfo2 struct
4864  ********************************************************************/
4865
4866 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4867                                         struct spoolss_DriverInfo2 *r,
4868                                         const struct spoolss_DriverInfo8 *driver,
4869                                         const char *servername)
4870
4871 {
4872         const char *cservername = canon_servername(servername);
4873
4874         r->version              = driver->version;
4875
4876         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4877         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4878         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4879         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4880
4881         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4882                                driver->architecture,
4883                                driver->version,
4884                                driver->driver_path,
4885                                r->driver_path);
4886
4887         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4888                                driver->architecture,
4889                                driver->version,
4890                                driver->data_file,
4891                                r->data_file);
4892
4893         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4894                                driver->architecture,
4895                                driver->version,
4896                                driver->config_file,
4897                                r->config_file);
4898
4899         return WERR_OK;
4900 }
4901
4902 /********************************************************************
4903  * fill a spoolss_DriverInfo3 struct
4904  ********************************************************************/
4905
4906 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4907                                         struct spoolss_DriverInfo3 *r,
4908                                         const struct spoolss_DriverInfo8 *driver,
4909                                         const char *servername)
4910 {
4911         const char *cservername = canon_servername(servername);
4912
4913         r->version              = driver->version;
4914
4915         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4916         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4917         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4918         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4919
4920         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4921                                driver->architecture,
4922                                driver->version,
4923                                driver->driver_path,
4924                                r->driver_path);
4925
4926         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4927                                driver->architecture,
4928                                driver->version,
4929                                driver->data_file,
4930                                r->data_file);
4931
4932         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4933                                driver->architecture,
4934                                driver->version,
4935                                driver->config_file,
4936                                r->config_file);
4937
4938         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4939                                driver->architecture,
4940                                driver->version,
4941                                driver->help_file,
4942                                r->help_file);
4943
4944         FILL_DRIVER_STRING(mem_ctx,
4945                            driver->monitor_name,
4946                            r->monitor_name);
4947
4948         FILL_DRIVER_STRING(mem_ctx,
4949                            driver->default_datatype,
4950                            r->default_datatype);
4951
4952         return string_array_from_driver_info(mem_ctx,
4953                                              driver->dependent_files,
4954                                              &r->dependent_files,
4955                                              cservername,
4956                                              driver->architecture,
4957                                              driver->version);
4958 }
4959
4960 /********************************************************************
4961  * fill a spoolss_DriverInfo4 struct
4962  ********************************************************************/
4963
4964 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4965                                         struct spoolss_DriverInfo4 *r,
4966                                         const struct spoolss_DriverInfo8 *driver,
4967                                         const char *servername)
4968 {
4969         const char *cservername = canon_servername(servername);
4970         WERROR result;
4971
4972         r->version              = driver->version;
4973
4974         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4975         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4976         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4977         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4978
4979         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4980                                driver->architecture,
4981                                driver->version,
4982                                driver->driver_path,
4983                                r->driver_path);
4984
4985         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4986                                driver->architecture,
4987                                driver->version,
4988                                driver->data_file,
4989                                r->data_file);
4990
4991         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4992                                driver->architecture,
4993                                driver->version,
4994                                driver->config_file,
4995                                r->config_file);
4996
4997         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998                                driver->architecture,
4999                                driver->version,
5000                                driver->help_file,
5001                                r->help_file);
5002
5003         result = string_array_from_driver_info(mem_ctx,
5004                                                driver->dependent_files,
5005                                                &r->dependent_files,
5006                                                cservername,
5007                                                driver->architecture,
5008                                                driver->version);
5009         if (!W_ERROR_IS_OK(result)) {
5010                 return result;
5011         }
5012
5013         FILL_DRIVER_STRING(mem_ctx,
5014                            driver->monitor_name,
5015                            r->monitor_name);
5016
5017         FILL_DRIVER_STRING(mem_ctx,
5018                            driver->default_datatype,
5019                            r->default_datatype);
5020
5021
5022         result = string_array_from_driver_info(mem_ctx,
5023                                                driver->previous_names,
5024                                                &r->previous_names,
5025                                                NULL, NULL, 0);
5026
5027         return result;
5028 }
5029
5030 /********************************************************************
5031  * fill a spoolss_DriverInfo5 struct
5032  ********************************************************************/
5033
5034 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5035                                         struct spoolss_DriverInfo5 *r,
5036                                         const struct spoolss_DriverInfo8 *driver,
5037                                         const char *servername)
5038 {
5039         const char *cservername = canon_servername(servername);
5040
5041         r->version              = driver->version;
5042
5043         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5044         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5045         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5046         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5047
5048         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5049                                driver->architecture,
5050                                driver->version,
5051                                driver->driver_path,
5052                                r->driver_path);
5053
5054         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5055                                driver->architecture,
5056                                driver->version,
5057                                driver->data_file,
5058                                r->data_file);
5059
5060         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5061                                driver->architecture,
5062                                driver->version,
5063                                driver->config_file,
5064                                r->config_file);
5065
5066         r->driver_attributes    = 0;
5067         r->config_version       = 0;
5068         r->driver_version       = 0;
5069
5070         return WERR_OK;
5071 }
5072 /********************************************************************
5073  * fill a spoolss_DriverInfo6 struct
5074  ********************************************************************/
5075
5076 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5077                                         struct spoolss_DriverInfo6 *r,
5078                                         const struct spoolss_DriverInfo8 *driver,
5079                                         const char *servername)
5080 {
5081         const char *cservername = canon_servername(servername);
5082         WERROR result;
5083
5084         r->version              = driver->version;
5085
5086         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5087         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5088         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5089         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5090
5091         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5092                                driver->architecture,
5093                                driver->version,
5094                                driver->driver_path,
5095                                r->driver_path);
5096
5097         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5098                                driver->architecture,
5099                                driver->version,
5100                                driver->data_file,
5101                                r->data_file);
5102
5103         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5104                                driver->architecture,
5105                                driver->version,
5106                                driver->config_file,
5107                                r->config_file);
5108
5109         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5110                                driver->architecture,
5111                                driver->version,
5112                                driver->help_file,
5113                                r->help_file);
5114
5115         FILL_DRIVER_STRING(mem_ctx,
5116                            driver->monitor_name,
5117                            r->monitor_name);
5118
5119         FILL_DRIVER_STRING(mem_ctx,
5120                            driver->default_datatype,
5121                            r->default_datatype);
5122
5123         result = string_array_from_driver_info(mem_ctx,
5124                                                driver->dependent_files,
5125                                                &r->dependent_files,
5126                                                cservername,
5127                                                driver->architecture,
5128                                                driver->version);
5129         if (!W_ERROR_IS_OK(result)) {
5130                 return result;
5131         }
5132
5133         result = string_array_from_driver_info(mem_ctx,
5134                                                driver->previous_names,
5135                                                &r->previous_names,
5136                                                NULL, NULL, 0);
5137         if (!W_ERROR_IS_OK(result)) {
5138                 return result;
5139         }
5140
5141         r->driver_date          = driver->driver_date;
5142         r->driver_version       = driver->driver_version;
5143
5144         FILL_DRIVER_STRING(mem_ctx,
5145                            driver->manufacturer_name,
5146                            r->manufacturer_name);
5147         FILL_DRIVER_STRING(mem_ctx,
5148                            driver->manufacturer_url,
5149                            r->manufacturer_url);
5150         FILL_DRIVER_STRING(mem_ctx,
5151                            driver->hardware_id,
5152                            r->hardware_id);
5153         FILL_DRIVER_STRING(mem_ctx,
5154                            driver->provider,
5155                            r->provider);
5156
5157         return WERR_OK;
5158 }
5159
5160 /********************************************************************
5161  * fill a spoolss_DriverInfo8 struct
5162  ********************************************************************/
5163
5164 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5165                                         struct spoolss_DriverInfo8 *r,
5166                                         const struct spoolss_DriverInfo8 *driver,
5167                                         const char *servername)
5168 {
5169         const char *cservername = canon_servername(servername);
5170         WERROR result;
5171
5172         r->version              = driver->version;
5173
5174         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5175         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5176         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5177         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5178
5179         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5180                                driver->architecture,
5181                                driver->version,
5182                                driver->driver_path,
5183                                r->driver_path);
5184
5185         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5186                                driver->architecture,
5187                                driver->version,
5188                                driver->data_file,
5189                                r->data_file);
5190
5191         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5192                                driver->architecture,
5193                                driver->version,
5194                                driver->config_file,
5195                                r->config_file);
5196
5197         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5198                                driver->architecture,
5199                                driver->version,
5200                                driver->help_file,
5201                                r->help_file);
5202
5203         FILL_DRIVER_STRING(mem_ctx,
5204                            driver->monitor_name,
5205                            r->monitor_name);
5206
5207         FILL_DRIVER_STRING(mem_ctx,
5208                            driver->default_datatype,
5209                            r->default_datatype);
5210
5211         result = string_array_from_driver_info(mem_ctx,
5212                                                driver->dependent_files,
5213                                                &r->dependent_files,
5214                                                cservername,
5215                                                driver->architecture,
5216                                                driver->version);
5217         if (!W_ERROR_IS_OK(result)) {
5218                 return result;
5219         }
5220
5221         result = string_array_from_driver_info(mem_ctx,
5222                                                driver->previous_names,
5223                                                &r->previous_names,
5224                                                NULL, NULL, 0);
5225         if (!W_ERROR_IS_OK(result)) {
5226                 return result;
5227         }
5228
5229         r->driver_date          = driver->driver_date;
5230         r->driver_version       = driver->driver_version;
5231
5232         FILL_DRIVER_STRING(mem_ctx,
5233                            driver->manufacturer_name,
5234                            r->manufacturer_name);
5235         FILL_DRIVER_STRING(mem_ctx,
5236                            driver->manufacturer_url,
5237                            r->manufacturer_url);
5238         FILL_DRIVER_STRING(mem_ctx,
5239                            driver->hardware_id,
5240                            r->hardware_id);
5241         FILL_DRIVER_STRING(mem_ctx,
5242                            driver->provider,
5243                            r->provider);
5244
5245         FILL_DRIVER_STRING(mem_ctx,
5246                            driver->print_processor,
5247                            r->print_processor);
5248         FILL_DRIVER_STRING(mem_ctx,
5249                            driver->vendor_setup,
5250                            r->vendor_setup);
5251
5252         result = string_array_from_driver_info(mem_ctx,
5253                                                driver->color_profiles,
5254                                                &r->color_profiles,
5255                                                NULL, NULL, 0);
5256         if (!W_ERROR_IS_OK(result)) {
5257                 return result;
5258         }
5259
5260         FILL_DRIVER_STRING(mem_ctx,
5261                            driver->inf_path,
5262                            r->inf_path);
5263
5264         r->printer_driver_attributes    = driver->printer_driver_attributes;
5265
5266         result = string_array_from_driver_info(mem_ctx,
5267                                                driver->core_driver_dependencies,
5268                                                &r->core_driver_dependencies,
5269                                                NULL, NULL, 0);
5270         if (!W_ERROR_IS_OK(result)) {
5271                 return result;
5272         }
5273
5274         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5275         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5276
5277         return WERR_OK;
5278 }
5279
5280 #if 0 /* disabled until marshalling issues are resolved - gd */
5281 /********************************************************************
5282  ********************************************************************/
5283
5284 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5285                                           struct spoolss_DriverFileInfo *r,
5286                                           const char *cservername,
5287                                           const char *file_name,
5288                                           enum spoolss_DriverFileType file_type,
5289                                           uint32_t file_version)
5290 {
5291         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5292                                           cservername, file_name);
5293         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5294         r->file_type    = file_type;
5295         r->file_version = file_version;
5296
5297         return WERR_OK;
5298 }
5299
5300 /********************************************************************
5301  ********************************************************************/
5302
5303 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5304                                                  const struct spoolss_DriverInfo8 *driver,
5305                                                  const char *cservername,
5306                                                  struct spoolss_DriverFileInfo **info_p,
5307                                                  uint32_t *count_p)
5308 {
5309         struct spoolss_DriverFileInfo *info = NULL;
5310         uint32_t count = 0;
5311         WERROR result;
5312         uint32_t i;
5313
5314         *info_p = NULL;
5315         *count_p = 0;
5316
5317         if (strlen(driver->driver_path)) {
5318                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5319                                             struct spoolss_DriverFileInfo,
5320                                             count + 1);
5321                 W_ERROR_HAVE_NO_MEMORY(info);
5322                 result = fill_spoolss_DriverFileInfo(info,
5323                                                      &info[count],
5324                                                      cservername,
5325                                                      driver->driver_path,
5326                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5327                                                      0);
5328                 W_ERROR_NOT_OK_RETURN(result);
5329                 count++;
5330         }
5331
5332         if (strlen(driver->config_file)) {
5333                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5334                                             struct spoolss_DriverFileInfo,
5335                                             count + 1);
5336                 W_ERROR_HAVE_NO_MEMORY(info);
5337                 result = fill_spoolss_DriverFileInfo(info,
5338                                                      &info[count],
5339                                                      cservername,
5340                                                      driver->config_file,
5341                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5342                                                      0);
5343                 W_ERROR_NOT_OK_RETURN(result);
5344                 count++;
5345         }
5346
5347         if (strlen(driver->data_file)) {
5348                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5349                                             struct spoolss_DriverFileInfo,
5350                                             count + 1);
5351                 W_ERROR_HAVE_NO_MEMORY(info);
5352                 result = fill_spoolss_DriverFileInfo(info,
5353                                                      &info[count],
5354                                                      cservername,
5355                                                      driver->data_file,
5356                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5357                                                      0);
5358                 W_ERROR_NOT_OK_RETURN(result);
5359                 count++;
5360         }
5361
5362         if (strlen(driver->help_file)) {
5363                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5364                                             struct spoolss_DriverFileInfo,
5365                                             count + 1);
5366                 W_ERROR_HAVE_NO_MEMORY(info);
5367                 result = fill_spoolss_DriverFileInfo(info,
5368                                                      &info[count],
5369                                                      cservername,
5370                                                      driver->help_file,
5371                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5372                                                      0);
5373                 W_ERROR_NOT_OK_RETURN(result);
5374                 count++;
5375         }
5376
5377         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5378                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5379                                             struct spoolss_DriverFileInfo,
5380                                             count + 1);
5381                 W_ERROR_HAVE_NO_MEMORY(info);
5382                 result = fill_spoolss_DriverFileInfo(info,
5383                                                      &info[count],
5384                                                      cservername,
5385                                                      driver->dependent_files[i],
5386                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5387                                                      0);
5388                 W_ERROR_NOT_OK_RETURN(result);
5389                 count++;
5390         }
5391
5392         *info_p = info;
5393         *count_p = count;
5394
5395         return WERR_OK;
5396 }
5397
5398 /********************************************************************
5399  * fill a spoolss_DriverInfo101 struct
5400  ********************************************************************/
5401
5402 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5403                                           struct spoolss_DriverInfo101 *r,
5404                                           const struct spoolss_DriverInfo8 *driver,
5405                                           const char *servername)
5406 {
5407         const char *cservername = canon_servername(servername);
5408         WERROR result;
5409
5410         r->version              = driver->version;
5411
5412         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5413         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5414         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5415         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5416
5417         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5418                                                     cservername,
5419                                                     &r->file_info,
5420                                                     &r->file_count);
5421         if (!W_ERROR_IS_OK(result)) {
5422                 return result;
5423         }
5424
5425         FILL_DRIVER_STRING(mem_ctx,
5426                            driver->monitor_name,
5427                            r->monitor_name);
5428
5429         FILL_DRIVER_STRING(mem_ctx,
5430                            driver->default_datatype,
5431                            r->default_datatype);
5432
5433         result = string_array_from_driver_info(mem_ctx,
5434                                                driver->previous_names,
5435                                                &r->previous_names,
5436                                                NULL, NULL, 0);
5437         if (!W_ERROR_IS_OK(result)) {
5438                 return result;
5439         }
5440
5441         r->driver_date          = driver->driver_date;
5442         r->driver_version       = driver->driver_version;
5443
5444         FILL_DRIVER_STRING(mem_ctx,
5445                            driver->manufacturer_name,
5446                            r->manufacturer_name);
5447         FILL_DRIVER_STRING(mem_ctx,
5448                            driver->manufacturer_url,
5449                            r->manufacturer_url);
5450         FILL_DRIVER_STRING(mem_ctx,
5451                            driver->hardware_id,
5452                            r->hardware_id);
5453         FILL_DRIVER_STRING(mem_ctx,
5454                            driver->provider,
5455                            r->provider);
5456
5457         return WERR_OK;
5458 }
5459 #endif
5460 /********************************************************************
5461  ********************************************************************/
5462
5463 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5464                                                   const struct auth_serversupplied_info *session_info,
5465                                                   struct messaging_context *msg_ctx,
5466                                                   uint32_t level,
5467                                                   union spoolss_DriverInfo *r,
5468                                                   int snum,
5469                                                   const char *servername,
5470                                                   const char *architecture,
5471                                                   uint32_t version)
5472 {
5473         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5474         struct spoolss_DriverInfo8 *driver;
5475         WERROR result;
5476
5477         if (level == 101) {
5478                 return WERR_UNKNOWN_LEVEL;
5479         }
5480
5481         result = winreg_get_printer(mem_ctx,
5482                                     session_info,
5483                                     msg_ctx,
5484                                     lp_const_servicename(snum),
5485                                     &pinfo2);
5486
5487         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5488                 win_errstr(result)));
5489
5490         if (!W_ERROR_IS_OK(result)) {
5491                 return WERR_INVALID_PRINTER_NAME;
5492         }
5493
5494         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5495                                    architecture,
5496                                    pinfo2->drivername, version, &driver);
5497
5498         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5499                 win_errstr(result)));
5500
5501         if (!W_ERROR_IS_OK(result)) {
5502                 /*
5503                  * Is this a W2k client ?
5504                  */
5505
5506                 if (version < 3) {
5507                         talloc_free(pinfo2);
5508                         return WERR_UNKNOWN_PRINTER_DRIVER;
5509                 }
5510
5511                 /* Yes - try again with a WinNT driver. */
5512                 version = 2;
5513                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5514                                            architecture,
5515                                            pinfo2->drivername,
5516                                            version, &driver);
5517                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5518                         win_errstr(result)));
5519                 if (!W_ERROR_IS_OK(result)) {
5520                         talloc_free(pinfo2);
5521                         return WERR_UNKNOWN_PRINTER_DRIVER;
5522                 }
5523         }
5524
5525         switch (level) {
5526         case 1:
5527                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5528                 break;
5529         case 2:
5530                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5531                 break;
5532         case 3:
5533                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5534                 break;
5535         case 4:
5536                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5537                 break;
5538         case 5:
5539                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5540                 break;
5541         case 6:
5542                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5543                 break;
5544         case 8:
5545                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5546                 break;
5547 #if 0 /* disabled until marshalling issues are resolved - gd */
5548         case 101:
5549                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5550                 break;
5551 #endif
5552         default:
5553                 result = WERR_UNKNOWN_LEVEL;
5554                 break;
5555         }
5556
5557         talloc_free(pinfo2);
5558         talloc_free(driver);
5559
5560         return result;
5561 }
5562
5563 /****************************************************************
5564  _spoolss_GetPrinterDriver2
5565 ****************************************************************/
5566
5567 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5568                                   struct spoolss_GetPrinterDriver2 *r)
5569 {
5570         struct printer_handle *printer;
5571         WERROR result;
5572
5573         int snum;
5574
5575         /* that's an [in out] buffer */
5576
5577         if (!r->in.buffer && (r->in.offered != 0)) {
5578                 return WERR_INVALID_PARAM;
5579         }
5580
5581         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5582
5583         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5584                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5585                 return WERR_INVALID_PRINTER_NAME;
5586         }
5587
5588         *r->out.needed = 0;
5589         *r->out.server_major_version = 0;
5590         *r->out.server_minor_version = 0;
5591
5592         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5593                 return WERR_BADFID;
5594         }
5595
5596         result = construct_printer_driver_info_level(p->mem_ctx,
5597                                                      get_session_info_system(),
5598                                                      p->msg_ctx,
5599                                                      r->in.level, r->out.info,
5600                                                      snum, printer->servername,
5601                                                      r->in.architecture,
5602                                                      r->in.client_major_version);
5603         if (!W_ERROR_IS_OK(result)) {
5604                 TALLOC_FREE(r->out.info);
5605                 return result;
5606         }
5607
5608         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5609                                                r->out.info, r->in.level);
5610         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5611
5612         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5613 }
5614
5615
5616 /****************************************************************
5617  _spoolss_StartPagePrinter
5618 ****************************************************************/
5619
5620 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5621                                  struct spoolss_StartPagePrinter *r)
5622 {
5623         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5624
5625         if (!Printer) {
5626                 DEBUG(3,("_spoolss_StartPagePrinter: "
5627                         "Error in startpageprinter printer handle\n"));
5628                 return WERR_BADFID;
5629         }
5630
5631         Printer->page_started = true;
5632         return WERR_OK;
5633 }
5634
5635 /****************************************************************
5636  _spoolss_EndPagePrinter
5637 ****************************************************************/
5638
5639 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5640                                struct spoolss_EndPagePrinter *r)
5641 {
5642         int snum;
5643
5644         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5645
5646         if (!Printer) {
5647                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5648                         OUR_HANDLE(r->in.handle)));
5649                 return WERR_BADFID;
5650         }
5651
5652         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5653                 return WERR_BADFID;
5654
5655         Printer->page_started = false;
5656         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5657
5658         return WERR_OK;
5659 }
5660
5661 /****************************************************************
5662  _spoolss_StartDocPrinter
5663 ****************************************************************/
5664
5665 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5666                                 struct spoolss_StartDocPrinter *r)
5667 {
5668         struct spoolss_DocumentInfo1 *info_1;
5669         int snum;
5670         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5671         WERROR werr;
5672
5673         if (!Printer) {
5674                 DEBUG(2,("_spoolss_StartDocPrinter: "
5675                         "Invalid handle (%s:%u:%u)\n",
5676                         OUR_HANDLE(r->in.handle)));
5677                 return WERR_BADFID;
5678         }
5679
5680         if (Printer->jobid) {
5681                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5682                           "StartDocPrinter called twice! "
5683                           "(existing jobid = %d)\n", Printer->jobid));
5684                 return WERR_INVALID_HANDLE;
5685         }
5686
5687         if (r->in.level != 1) {
5688                 return WERR_UNKNOWN_LEVEL;
5689         }
5690
5691         info_1 = r->in.info.info1;
5692
5693         /*
5694          * a nice thing with NT is it doesn't listen to what you tell it.
5695          * when asked to send _only_ RAW datas, it tries to send datas
5696          * in EMF format.
5697          *
5698          * So I add checks like in NT Server ...
5699          */
5700
5701         if (info_1->datatype) {
5702                 if (strcmp(info_1->datatype, "RAW") != 0) {
5703                         *r->out.job_id = 0;
5704                         return WERR_INVALID_DATATYPE;
5705                 }
5706         }
5707
5708         /* get the share number of the printer */
5709         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5710                 return WERR_BADFID;
5711         }
5712
5713         werr = print_job_start(p->session_info,
5714                                p->msg_ctx,
5715                                p->client_id->name,
5716                                snum,
5717                                info_1->document_name,
5718                                info_1->output_file,
5719                                Printer->devmode,
5720                                &Printer->jobid);
5721
5722         /* An error occured in print_job_start() so return an appropriate
5723            NT error code. */
5724
5725         if (!W_ERROR_IS_OK(werr)) {
5726                 return werr;
5727         }
5728
5729         Printer->document_started = true;
5730         *r->out.job_id = Printer->jobid;
5731
5732         return WERR_OK;
5733 }
5734
5735 /****************************************************************
5736  _spoolss_EndDocPrinter
5737 ****************************************************************/
5738
5739 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5740                               struct spoolss_EndDocPrinter *r)
5741 {
5742         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5743         NTSTATUS status;
5744         int snum;
5745
5746         if (!Printer) {
5747                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5748                         OUR_HANDLE(r->in.handle)));
5749                 return WERR_BADFID;
5750         }
5751
5752         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5753                 return WERR_BADFID;
5754         }
5755
5756         Printer->document_started = false;
5757         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5758         if (!NT_STATUS_IS_OK(status)) {
5759                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5760                           "print_job_end failed [%s]\n",
5761                           nt_errstr(status)));
5762         }
5763
5764         Printer->jobid = 0;
5765         return ntstatus_to_werror(status);
5766 }
5767
5768 /****************************************************************
5769  _spoolss_WritePrinter
5770 ****************************************************************/
5771
5772 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5773                              struct spoolss_WritePrinter *r)
5774 {
5775         ssize_t buffer_written;
5776         int snum;
5777         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5778
5779         if (!Printer) {
5780                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5781                         OUR_HANDLE(r->in.handle)));
5782                 *r->out.num_written = r->in._data_size;
5783                 return WERR_BADFID;
5784         }
5785
5786         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5787                 return WERR_BADFID;
5788
5789         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5790         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5791                                                    snum, Printer->jobid,
5792                                                    (const char *)r->in.data.data,
5793                                                    (size_t)r->in._data_size);
5794         if (buffer_written == (ssize_t)-1) {
5795                 *r->out.num_written = 0;
5796                 if (errno == ENOSPC)
5797                         return WERR_NO_SPOOL_SPACE;
5798                 else
5799                         return WERR_ACCESS_DENIED;
5800         }
5801
5802         *r->out.num_written = r->in._data_size;
5803
5804         return WERR_OK;
5805 }
5806
5807 /********************************************************************
5808  * api_spoolss_getprinter
5809  * called from the spoolss dispatcher
5810  *
5811  ********************************************************************/
5812
5813 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5814                               struct pipes_struct *p)
5815 {
5816         const struct auth_serversupplied_info *session_info = p->session_info;
5817         int snum;
5818         WERROR errcode = WERR_BADFUNC;
5819         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5820
5821         if (!Printer) {
5822                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5823                         OUR_HANDLE(handle)));
5824                 return WERR_BADFID;
5825         }
5826
5827         if (!get_printer_snum(p, handle, &snum, NULL))
5828                 return WERR_BADFID;
5829
5830         switch (command) {
5831         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5832                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5833                 break;
5834         case SPOOLSS_PRINTER_CONTROL_RESUME:
5835         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5836                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5837                 break;
5838         case SPOOLSS_PRINTER_CONTROL_PURGE:
5839                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5840                 break;
5841         default:
5842                 return WERR_UNKNOWN_LEVEL;
5843         }
5844
5845         return errcode;
5846 }
5847
5848
5849 /****************************************************************
5850  _spoolss_AbortPrinter
5851  * From MSDN: "Deletes printer's spool file if printer is configured
5852  * for spooling"
5853 ****************************************************************/
5854
5855 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5856                              struct spoolss_AbortPrinter *r)
5857 {
5858         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5859         int             snum;
5860         WERROR          errcode = WERR_OK;
5861
5862         if (!Printer) {
5863                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5864                         OUR_HANDLE(r->in.handle)));
5865                 return WERR_BADFID;
5866         }
5867
5868         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5869                 return WERR_BADFID;
5870
5871         if (!Printer->document_started) {
5872                 return WERR_SPL_NO_STARTDOC;
5873         }
5874
5875         errcode = print_job_delete(p->session_info,
5876                                    p->msg_ctx,
5877                                    snum,
5878                                    Printer->jobid);
5879
5880         return errcode;
5881 }
5882
5883 /********************************************************************
5884  * called by spoolss_api_setprinter
5885  * when updating a printer description
5886  ********************************************************************/
5887
5888 static WERROR update_printer_sec(struct policy_handle *handle,
5889                                  struct pipes_struct *p,
5890                                  struct sec_desc_buf *secdesc_ctr)
5891 {
5892         struct spoolss_security_descriptor *new_secdesc = NULL;
5893         struct spoolss_security_descriptor *old_secdesc = NULL;
5894         const char *printer;
5895         WERROR result;
5896         int snum;
5897
5898         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5899
5900         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5901                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5902                          OUR_HANDLE(handle)));
5903
5904                 result = WERR_BADFID;
5905                 goto done;
5906         }
5907
5908         if (secdesc_ctr == NULL) {
5909                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5910                 result = WERR_INVALID_PARAM;
5911                 goto done;
5912         }
5913         printer = lp_const_servicename(snum);
5914
5915         /* Check the user has permissions to change the security
5916            descriptor.  By experimentation with two NT machines, the user
5917            requires Full Access to the printer to change security
5918            information. */
5919
5920         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5921                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5922                 result = WERR_ACCESS_DENIED;
5923                 goto done;
5924         }
5925
5926         /* NT seems to like setting the security descriptor even though
5927            nothing may have actually changed. */
5928         result = winreg_get_printer_secdesc(p->mem_ctx,
5929                                             get_session_info_system(),
5930                                             p->msg_ctx,
5931                                             printer,
5932                                             &old_secdesc);
5933         if (!W_ERROR_IS_OK(result)) {
5934                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5935                 result = WERR_BADFID;
5936                 goto done;
5937         }
5938
5939         if (DEBUGLEVEL >= 10) {
5940                 struct security_acl *the_acl;
5941                 int i;
5942
5943                 the_acl = old_secdesc->dacl;
5944                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5945                            printer, the_acl->num_aces));
5946
5947                 for (i = 0; i < the_acl->num_aces; i++) {
5948                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5949                                            &the_acl->aces[i].trustee),
5950                                   the_acl->aces[i].access_mask));
5951                 }
5952
5953                 the_acl = secdesc_ctr->sd->dacl;
5954
5955                 if (the_acl) {
5956                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5957                                    printer, the_acl->num_aces));
5958
5959                         for (i = 0; i < the_acl->num_aces; i++) {
5960                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5961                                                    &the_acl->aces[i].trustee),
5962                                            the_acl->aces[i].access_mask));
5963                         }
5964                 } else {
5965                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5966                 }
5967         }
5968
5969         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5970         if (new_secdesc == NULL) {
5971                 result = WERR_NOMEM;
5972                 goto done;
5973         }
5974
5975         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5976                 result = WERR_OK;
5977                 goto done;
5978         }
5979
5980         result = winreg_set_printer_secdesc(p->mem_ctx,
5981                                             get_session_info_system(),
5982                                             p->msg_ctx,
5983                                             printer,
5984                                             new_secdesc);
5985
5986  done:
5987         return result;
5988 }
5989
5990 /********************************************************************
5991  Canonicalize printer info from a client
5992  ********************************************************************/
5993
5994 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5995                              struct spoolss_SetPrinterInfo2 *info2,
5996                              int snum)
5997 {
5998         fstring printername;
5999         const char *p;
6000
6001         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6002                 "portname=%s drivername=%s comment=%s location=%s\n",
6003                 info2->servername, info2->printername, info2->sharename,
6004                 info2->portname, info2->drivername, info2->comment,
6005                 info2->location));
6006
6007         /* we force some elements to "correct" values */
6008         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6009         if (info2->servername == NULL) {
6010                 return false;
6011         }
6012         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6013         if (info2->sharename == NULL) {
6014                 return false;
6015         }
6016
6017         /* check to see if we allow printername != sharename */
6018         if (lp_force_printername(snum)) {
6019                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6020                                         global_myname(), info2->sharename);
6021         } else {
6022                 /* make sure printername is in \\server\printername format */
6023                 fstrcpy(printername, info2->printername);
6024                 p = printername;
6025                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6026                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6027                                 p++;
6028                 }
6029
6030                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6031                                         global_myname(), p);
6032         }
6033         if (info2->printername == NULL) {
6034                 return false;
6035         }
6036
6037         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6038         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6039
6040         return true;
6041 }
6042
6043 /****************************************************************************
6044 ****************************************************************************/
6045
6046 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6047 {
6048         char *cmd = lp_addport_cmd();
6049         char *command = NULL;
6050         int ret;
6051         bool is_print_op = false;
6052
6053         if ( !*cmd ) {
6054                 return WERR_ACCESS_DENIED;
6055         }
6056
6057         command = talloc_asprintf(ctx,
6058                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6059         if (!command) {
6060                 return WERR_NOMEM;
6061         }
6062
6063         if ( token )
6064                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6065
6066         DEBUG(10,("Running [%s]\n", command));
6067
6068         /********* BEGIN SePrintOperatorPrivilege **********/
6069
6070         if ( is_print_op )
6071                 become_root();
6072
6073         ret = smbrun(command, NULL);
6074
6075         if ( is_print_op )
6076                 unbecome_root();
6077
6078         /********* END SePrintOperatorPrivilege **********/
6079
6080         DEBUGADD(10,("returned [%d]\n", ret));
6081
6082         TALLOC_FREE(command);
6083
6084         if ( ret != 0 ) {
6085                 return WERR_ACCESS_DENIED;
6086         }
6087
6088         return WERR_OK;
6089 }
6090
6091 /****************************************************************************
6092 ****************************************************************************/
6093
6094 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6095                              struct spoolss_SetPrinterInfo2 *info2,
6096                              const char *remote_machine,
6097                              struct messaging_context *msg_ctx)
6098 {
6099         char *cmd = lp_addprinter_cmd();
6100         char **qlines;
6101         char *command = NULL;
6102         int numlines;
6103         int ret;
6104         int fd;
6105         bool is_print_op = false;
6106
6107         if (!remote_machine) {
6108                 return false;
6109         }
6110
6111         command = talloc_asprintf(ctx,
6112                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6113                         cmd, info2->printername, info2->sharename,
6114                         info2->portname, info2->drivername,
6115                         info2->location, info2->comment, remote_machine);
6116         if (!command) {
6117                 return false;
6118         }
6119
6120         if ( token )
6121                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6122
6123         DEBUG(10,("Running [%s]\n", command));
6124
6125         /********* BEGIN SePrintOperatorPrivilege **********/
6126
6127         if ( is_print_op )
6128                 become_root();
6129
6130         if ( (ret = smbrun(command, &fd)) == 0 ) {
6131                 /* Tell everyone we updated smb.conf. */
6132                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6133         }
6134
6135         if ( is_print_op )
6136                 unbecome_root();
6137
6138         /********* END SePrintOperatorPrivilege **********/
6139
6140         DEBUGADD(10,("returned [%d]\n", ret));
6141
6142         TALLOC_FREE(command);
6143
6144         if ( ret != 0 ) {
6145                 if (fd != -1)
6146                         close(fd);
6147                 return false;
6148         }
6149
6150         /* reload our services immediately */
6151         become_root();
6152         reload_services(msg_ctx, -1, false);
6153         unbecome_root();
6154
6155         numlines = 0;
6156         /* Get lines and convert them back to dos-codepage */
6157         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6158         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6159         close(fd);
6160
6161         /* Set the portname to what the script says the portname should be. */
6162         /* but don't require anything to be return from the script exit a good error code */
6163
6164         if (numlines) {
6165                 /* Set the portname to what the script says the portname should be. */
6166                 info2->portname = talloc_strdup(ctx, qlines[0]);
6167                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6168         }
6169
6170         TALLOC_FREE(qlines);
6171         return true;
6172 }
6173
6174 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6175                                const struct auth_serversupplied_info *session_info,
6176                                struct messaging_context *msg_ctx,
6177                                int snum,
6178                                struct spoolss_SetPrinterInfo2 *printer,
6179                                struct spoolss_PrinterInfo2 *old_printer)
6180 {
6181         bool force_update = (old_printer == NULL);
6182         const char *dnsdomname;
6183         const char *longname;
6184         const char *uncname;
6185         const char *spooling;
6186         DATA_BLOB buffer;
6187         WERROR result = WERR_OK;
6188
6189         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6190                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6191                 winreg_set_printer_dataex(mem_ctx,
6192                                           session_info,
6193                                           msg_ctx,
6194                                           printer->sharename,
6195                                           SPOOL_DSSPOOLER_KEY,
6196                                           SPOOL_REG_DRIVERNAME,
6197                                           REG_SZ,
6198                                           buffer.data,
6199                                           buffer.length);
6200
6201                 if (!force_update) {
6202                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6203                                 printer->drivername));
6204
6205                         notify_printer_driver(server_event_context(), msg_ctx,
6206                                               snum, printer->drivername ?
6207                                               printer->drivername : "");
6208                 }
6209         }
6210
6211         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6212                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6213                 winreg_set_printer_dataex(mem_ctx,
6214                                           session_info,
6215                                           msg_ctx,
6216                                           printer->sharename,
6217                                           SPOOL_DSSPOOLER_KEY,
6218                                           SPOOL_REG_DESCRIPTION,
6219                                           REG_SZ,
6220                                           buffer.data,
6221                                           buffer.length);
6222
6223                 if (!force_update) {
6224                         notify_printer_comment(server_event_context(), msg_ctx,
6225                                                snum, printer->comment ?
6226                                                printer->comment : "");
6227                 }
6228         }
6229
6230         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6231                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6232                 winreg_set_printer_dataex(mem_ctx,
6233                                           session_info,
6234                                           msg_ctx,
6235                                           printer->sharename,
6236                                           SPOOL_DSSPOOLER_KEY,
6237                                           SPOOL_REG_PRINTSHARENAME,
6238                                           REG_SZ,
6239                                           buffer.data,
6240                                           buffer.length);
6241
6242                 if (!force_update) {
6243                         notify_printer_sharename(server_event_context(),
6244                                                  msg_ctx,
6245                                                  snum, printer->sharename ?
6246                                                  printer->sharename : "");
6247                 }
6248         }
6249
6250         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6251                 const char *p;
6252
6253                 p = strrchr(printer->printername, '\\' );
6254                 if (p != NULL) {
6255                         p++;
6256                 } else {
6257                         p = printer->printername;
6258                 }
6259
6260                 push_reg_sz(mem_ctx, &buffer, p);
6261                 winreg_set_printer_dataex(mem_ctx,
6262                                           session_info,
6263                                           msg_ctx,
6264                                           printer->sharename,
6265                                           SPOOL_DSSPOOLER_KEY,
6266                                           SPOOL_REG_PRINTERNAME,
6267                                           REG_SZ,
6268                                           buffer.data,
6269                                           buffer.length);
6270
6271                 if (!force_update) {
6272                         notify_printer_printername(server_event_context(),
6273                                                    msg_ctx, snum, p ? p : "");
6274                 }
6275         }
6276
6277         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6278                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6279                 winreg_set_printer_dataex(mem_ctx,
6280                                           session_info,
6281                                           msg_ctx,
6282                                           printer->sharename,
6283                                           SPOOL_DSSPOOLER_KEY,
6284                                           SPOOL_REG_PORTNAME,
6285                                           REG_SZ,
6286                                           buffer.data,
6287                                           buffer.length);
6288
6289                 if (!force_update) {
6290                         notify_printer_port(server_event_context(),
6291                                             msg_ctx, snum, printer->portname ?
6292                                             printer->portname : "");
6293                 }
6294         }
6295
6296         if (force_update || !strequal(printer->location, old_printer->location)) {
6297                 push_reg_sz(mem_ctx, &buffer, printer->location);
6298                 winreg_set_printer_dataex(mem_ctx,
6299                                           session_info,
6300                                           msg_ctx,
6301                                           printer->sharename,
6302                                           SPOOL_DSSPOOLER_KEY,
6303                                           SPOOL_REG_LOCATION,
6304                                           REG_SZ,
6305                                           buffer.data,
6306                                           buffer.length);
6307
6308                 if (!force_update) {
6309                         notify_printer_location(server_event_context(),
6310                                                 msg_ctx, snum,
6311                                                 printer->location ?
6312                                                 printer->location : "");
6313                 }
6314         }
6315
6316         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6317                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6318                 winreg_set_printer_dataex(mem_ctx,
6319                                           session_info,
6320                                           msg_ctx,
6321                                           printer->sharename,
6322                                           SPOOL_DSSPOOLER_KEY,
6323                                           SPOOL_REG_PRINTSEPARATORFILE,
6324                                           REG_SZ,
6325                                           buffer.data,
6326                                           buffer.length);
6327
6328                 if (!force_update) {
6329                         notify_printer_sepfile(server_event_context(),
6330                                                msg_ctx, snum,
6331                                                printer->sepfile ?
6332                                                printer->sepfile : "");
6333                 }
6334         }
6335
6336         if (force_update || printer->starttime != old_printer->starttime) {
6337                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6338                 SIVAL(buffer.data, 0, printer->starttime);
6339                 winreg_set_printer_dataex(mem_ctx,
6340                                           session_info,
6341                                           msg_ctx,
6342                                           printer->sharename,
6343                                           SPOOL_DSSPOOLER_KEY,
6344                                           SPOOL_REG_PRINTSTARTTIME,
6345                                           REG_DWORD,
6346                                           buffer.data,
6347                                           buffer.length);
6348         }
6349
6350         if (force_update || printer->untiltime != old_printer->untiltime) {
6351                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6352                 SIVAL(buffer.data, 0, printer->untiltime);
6353                 winreg_set_printer_dataex(mem_ctx,
6354                                           session_info,
6355                                           msg_ctx,
6356                                           printer->sharename,
6357                                           SPOOL_DSSPOOLER_KEY,
6358                                           SPOOL_REG_PRINTENDTIME,
6359                                           REG_DWORD,
6360                                           buffer.data,
6361                                           buffer.length);
6362         }
6363
6364         if (force_update || printer->priority != old_printer->priority) {
6365                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6366                 SIVAL(buffer.data, 0, printer->priority);
6367                 winreg_set_printer_dataex(mem_ctx,
6368                                           session_info,
6369                                           msg_ctx,
6370                                           printer->sharename,
6371                                           SPOOL_DSSPOOLER_KEY,
6372                                           SPOOL_REG_PRIORITY,
6373                                           REG_DWORD,
6374                                           buffer.data,
6375                                           buffer.length);
6376         }
6377
6378         if (force_update || printer->attributes != old_printer->attributes) {
6379                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6380                 SIVAL(buffer.data, 0, (printer->attributes &
6381                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6382                 winreg_set_printer_dataex(mem_ctx,
6383                                           session_info,
6384                                           msg_ctx,
6385                                           printer->sharename,
6386                                           SPOOL_DSSPOOLER_KEY,
6387                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6388                                           REG_DWORD,
6389                                           buffer.data,
6390                                           buffer.length);
6391
6392                 switch (printer->attributes & 0x3) {
6393                         case 0:
6394                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6395                                 break;
6396                         case 1:
6397                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6398                                 break;
6399                         case 2:
6400                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6401                                 break;
6402                         default:
6403                                 spooling = "unknown";
6404                 }
6405                 push_reg_sz(mem_ctx, &buffer, spooling);
6406                 winreg_set_printer_dataex(mem_ctx,
6407                                           session_info,
6408                                           msg_ctx,
6409                                           printer->sharename,
6410                                           SPOOL_DSSPOOLER_KEY,
6411                                           SPOOL_REG_PRINTSPOOLING,
6412                                           REG_SZ,
6413                                           buffer.data,
6414                                           buffer.length);
6415         }
6416
6417         push_reg_sz(mem_ctx, &buffer, global_myname());
6418         winreg_set_printer_dataex(mem_ctx,
6419                                   session_info,
6420                                   msg_ctx,
6421                                   printer->sharename,
6422                                   SPOOL_DSSPOOLER_KEY,
6423                                   SPOOL_REG_SHORTSERVERNAME,
6424                                   REG_SZ,
6425                                   buffer.data,
6426                                   buffer.length);
6427
6428         dnsdomname = get_mydnsfullname();
6429         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6430                 longname = talloc_strdup(mem_ctx, dnsdomname);
6431         } else {
6432                 longname = talloc_strdup(mem_ctx, global_myname());
6433         }
6434         if (longname == NULL) {
6435                 result = WERR_NOMEM;
6436                 goto done;
6437         }
6438
6439         push_reg_sz(mem_ctx, &buffer, longname);
6440         winreg_set_printer_dataex(mem_ctx,
6441                                   session_info,
6442                                   msg_ctx,
6443                                   printer->sharename,
6444                                   SPOOL_DSSPOOLER_KEY,
6445                                   SPOOL_REG_SERVERNAME,
6446                                   REG_SZ,
6447                                   buffer.data,
6448                                   buffer.length);
6449
6450         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6451                                   global_myname(), printer->sharename);
6452         push_reg_sz(mem_ctx, &buffer, uncname);
6453         winreg_set_printer_dataex(mem_ctx,
6454                                   session_info,
6455                                   msg_ctx,
6456                                   printer->sharename,
6457                                   SPOOL_DSSPOOLER_KEY,
6458                                   SPOOL_REG_UNCNAME,
6459                                   REG_SZ,
6460                                   buffer.data,
6461                                   buffer.length);
6462
6463 done:
6464         return result;
6465 }
6466
6467 /********************************************************************
6468  * Called by spoolss_api_setprinter
6469  * when updating a printer description.
6470  ********************************************************************/
6471
6472 static WERROR update_printer(struct pipes_struct *p,
6473                              struct policy_handle *handle,
6474                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6475                              struct spoolss_DeviceMode *devmode)
6476 {
6477         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6478         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6479         struct spoolss_PrinterInfo2 *old_printer;
6480         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6481         int snum;
6482         WERROR result = WERR_OK;
6483         TALLOC_CTX *tmp_ctx;
6484
6485         DEBUG(8,("update_printer\n"));
6486
6487         tmp_ctx = talloc_new(p->mem_ctx);
6488         if (tmp_ctx == NULL) {
6489                 return WERR_NOMEM;
6490         }
6491
6492         if (!Printer) {
6493                 result = WERR_BADFID;
6494                 goto done;
6495         }
6496
6497         if (!get_printer_snum(p, handle, &snum, NULL)) {
6498                 result = WERR_BADFID;
6499                 goto done;
6500         }
6501
6502         result = winreg_get_printer(tmp_ctx,
6503                                     get_session_info_system(),
6504                                     p->msg_ctx,
6505                                     lp_const_servicename(snum),
6506                                     &old_printer);
6507         if (!W_ERROR_IS_OK(result)) {
6508                 result = WERR_BADFID;
6509                 goto done;
6510         }
6511
6512         /* Do sanity check on the requested changes for Samba */
6513         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6514                 result = WERR_INVALID_PARAM;
6515                 goto done;
6516         }
6517
6518         /* FIXME!!! If the driver has changed we really should verify that
6519            it is installed before doing much else   --jerry */
6520
6521         /* Check calling user has permission to update printer description */
6522         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6523                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6524                 result = WERR_ACCESS_DENIED;
6525                 goto done;
6526         }
6527
6528         /* Call addprinter hook */
6529         /* Check changes to see if this is really needed */
6530
6531         if (*lp_addprinter_cmd() &&
6532                         (!strequal(printer->drivername, old_printer->drivername) ||
6533                          !strequal(printer->comment, old_printer->comment) ||
6534                          !strequal(printer->portname, old_printer->portname) ||
6535                          !strequal(printer->location, old_printer->location)) )
6536         {
6537                 /* add_printer_hook() will call reload_services() */
6538                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6539                                       printer, p->client_id->addr,
6540                                       p->msg_ctx)) {
6541                         result = WERR_ACCESS_DENIED;
6542                         goto done;
6543                 }
6544         }
6545
6546         update_dsspooler(tmp_ctx,
6547                          get_session_info_system(),
6548                          p->msg_ctx,
6549                          snum,
6550                          printer,
6551                          old_printer);
6552
6553         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6554
6555         if (devmode == NULL) {
6556                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6557         }
6558         result = winreg_update_printer(tmp_ctx,
6559                                        get_session_info_system(),
6560                                        p->msg_ctx,
6561                                        printer->sharename,
6562                                        printer_mask,
6563                                        printer,
6564                                        devmode,
6565                                        NULL);
6566
6567 done:
6568         talloc_free(tmp_ctx);
6569
6570         return result;
6571 }
6572
6573 /****************************************************************************
6574 ****************************************************************************/
6575 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6576                                            struct policy_handle *handle,
6577                                            struct spoolss_SetPrinterInfo7 *info7)
6578 {
6579 #ifdef HAVE_ADS
6580         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6581         WERROR result;
6582         int snum;
6583         struct printer_handle *Printer;
6584
6585         if ( lp_security() != SEC_ADS ) {
6586                 return WERR_UNKNOWN_LEVEL;
6587         }
6588
6589         Printer = find_printer_index_by_hnd(p, handle);
6590
6591         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6592
6593         if (!Printer)
6594                 return WERR_BADFID;
6595
6596         if (!get_printer_snum(p, handle, &snum, NULL))
6597                 return WERR_BADFID;
6598
6599         result = winreg_get_printer(p->mem_ctx,
6600                                     get_session_info_system(),
6601                                     p->msg_ctx,
6602                                     lp_servicename(snum),
6603                                     &pinfo2);
6604         if (!W_ERROR_IS_OK(result)) {
6605                 return WERR_BADFID;
6606         }
6607
6608         nt_printer_publish(pinfo2,
6609                            get_session_info_system(),
6610                            p->msg_ctx,
6611                            pinfo2,
6612                            info7->action);
6613
6614         TALLOC_FREE(pinfo2);
6615         return WERR_OK;
6616 #else
6617         return WERR_UNKNOWN_LEVEL;
6618 #endif
6619 }
6620
6621 /********************************************************************
6622  ********************************************************************/
6623
6624 static WERROR update_printer_devmode(struct pipes_struct *p,
6625                                      struct policy_handle *handle,
6626                                      struct spoolss_DeviceMode *devmode)
6627 {
6628         int snum;
6629         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6630         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6631
6632         DEBUG(8,("update_printer_devmode\n"));
6633
6634         if (!Printer) {
6635                 return WERR_BADFID;
6636         }
6637
6638         if (!get_printer_snum(p, handle, &snum, NULL)) {
6639                 return WERR_BADFID;
6640         }
6641
6642         /* Check calling user has permission to update printer description */
6643         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6644                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6645                 return WERR_ACCESS_DENIED;
6646         }
6647
6648         return winreg_update_printer(p->mem_ctx,
6649                                      get_session_info_system(),
6650                                      p->msg_ctx,
6651                                      lp_const_servicename(snum),
6652                                      info2_mask,
6653                                      NULL,
6654                                      devmode,
6655                                      NULL);
6656 }
6657
6658
6659 /****************************************************************
6660  _spoolss_SetPrinter
6661 ****************************************************************/
6662
6663 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6664                            struct spoolss_SetPrinter *r)
6665 {
6666         WERROR result;
6667
6668         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6669
6670         if (!Printer) {
6671                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6672                         OUR_HANDLE(r->in.handle)));
6673                 return WERR_BADFID;
6674         }
6675
6676         /* check the level */
6677         switch (r->in.info_ctr->level) {
6678                 case 0:
6679                         return control_printer(r->in.handle, r->in.command, p);
6680                 case 2:
6681                         result = update_printer(p, r->in.handle,
6682                                                 r->in.info_ctr,
6683                                                 r->in.devmode_ctr->devmode);
6684                         if (!W_ERROR_IS_OK(result))
6685                                 return result;
6686                         if (r->in.secdesc_ctr->sd)
6687                                 result = update_printer_sec(r->in.handle, p,
6688                                                             r->in.secdesc_ctr);
6689                         return result;
6690                 case 3:
6691                         return update_printer_sec(r->in.handle, p,
6692                                                   r->in.secdesc_ctr);
6693                 case 7:
6694                         return publish_or_unpublish_printer(p, r->in.handle,
6695                                                             r->in.info_ctr->info.info7);
6696                 case 8:
6697                         return update_printer_devmode(p, r->in.handle,
6698                                                       r->in.devmode_ctr->devmode);
6699                 default:
6700                         return WERR_UNKNOWN_LEVEL;
6701         }
6702 }
6703
6704 /****************************************************************
6705  _spoolss_FindClosePrinterNotify
6706 ****************************************************************/
6707
6708 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6709                                        struct spoolss_FindClosePrinterNotify *r)
6710 {
6711         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6712
6713         if (!Printer) {
6714                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6715                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6716                 return WERR_BADFID;
6717         }
6718
6719         if (Printer->notify.cli_chan != NULL &&
6720             Printer->notify.cli_chan->active_connections > 0) {
6721                 int snum = -1;
6722
6723                 if (Printer->printer_type == SPLHND_PRINTER) {
6724                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6725                                 return WERR_BADFID;
6726                         }
6727                 }
6728
6729                 srv_spoolss_replycloseprinter(snum, Printer);
6730         }
6731
6732         Printer->notify.flags=0;
6733         Printer->notify.options=0;
6734         Printer->notify.localmachine[0]='\0';
6735         Printer->notify.printerlocal=0;
6736         TALLOC_FREE(Printer->notify.option);
6737
6738         return WERR_OK;
6739 }
6740
6741 /****************************************************************
6742  _spoolss_AddJob
6743 ****************************************************************/
6744
6745 WERROR _spoolss_AddJob(struct pipes_struct *p,
6746                        struct spoolss_AddJob *r)
6747 {
6748         if (!r->in.buffer && (r->in.offered != 0)) {
6749                 return WERR_INVALID_PARAM;
6750         }
6751
6752         /* this is what a NT server returns for AddJob. AddJob must fail on
6753          * non-local printers */
6754
6755         if (r->in.level != 1) {
6756                 return WERR_UNKNOWN_LEVEL;
6757         }
6758
6759         return WERR_INVALID_PARAM;
6760 }
6761
6762 /****************************************************************************
6763 fill_job_info1
6764 ****************************************************************************/
6765
6766 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6767                              struct spoolss_JobInfo1 *r,
6768                              const print_queue_struct *queue,
6769                              int position, int snum,
6770                              struct spoolss_PrinterInfo2 *pinfo2)
6771 {
6772         struct tm *t;
6773
6774         t = gmtime(&queue->time);
6775
6776         r->job_id               = queue->job;
6777
6778         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6779         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6780         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6781         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6782         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6783         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6784         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6785         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6786         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6787         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6788         r->text_status          = talloc_strdup(mem_ctx, "");
6789         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6790
6791         r->status               = nt_printj_status(queue->status);
6792         r->priority             = queue->priority;
6793         r->position             = position;
6794         r->total_pages          = queue->page_count;
6795         r->pages_printed        = 0; /* ??? */
6796
6797         init_systemtime(&r->submitted, t);
6798
6799         return WERR_OK;
6800 }
6801
6802 /****************************************************************************
6803 fill_job_info2
6804 ****************************************************************************/
6805
6806 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6807                              struct spoolss_JobInfo2 *r,
6808                              const print_queue_struct *queue,
6809                              int position, int snum,
6810                              struct spoolss_PrinterInfo2 *pinfo2,
6811                              struct spoolss_DeviceMode *devmode)
6812 {
6813         struct tm *t;
6814
6815         t = gmtime(&queue->time);
6816
6817         r->job_id               = queue->job;
6818
6819         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6820         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6821         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6822         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6823         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6824         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6825         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6826         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6827         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6828         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6829         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6830         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6831         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6832         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6833         r->parameters           = talloc_strdup(mem_ctx, "");
6834         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6835         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6836         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6837
6838         r->devmode              = devmode;
6839
6840         r->text_status          = talloc_strdup(mem_ctx, "");
6841         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6842
6843         r->secdesc              = NULL;
6844
6845         r->status               = nt_printj_status(queue->status);
6846         r->priority             = queue->priority;
6847         r->position             = position;
6848         r->start_time           = 0;
6849         r->until_time           = 0;
6850         r->total_pages          = queue->page_count;
6851         r->size                 = queue->size;
6852         init_systemtime(&r->submitted, t);
6853         r->time                 = 0;
6854         r->pages_printed        = 0; /* ??? */
6855
6856         return WERR_OK;
6857 }
6858
6859 /****************************************************************************
6860 fill_job_info3
6861 ****************************************************************************/
6862
6863 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6864                              struct spoolss_JobInfo3 *r,
6865                              const print_queue_struct *queue,
6866                              const print_queue_struct *next_queue,
6867                              int position, int snum,
6868                              struct spoolss_PrinterInfo2 *pinfo2)
6869 {
6870         r->job_id               = queue->job;
6871         r->next_job_id          = 0;
6872         if (next_queue) {
6873                 r->next_job_id  = next_queue->job;
6874         }
6875         r->reserved             = 0;
6876
6877         return WERR_OK;
6878 }
6879
6880 /****************************************************************************
6881  Enumjobs at level 1.
6882 ****************************************************************************/
6883
6884 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6885                               const print_queue_struct *queue,
6886                               uint32_t num_queues, int snum,
6887                               struct spoolss_PrinterInfo2 *pinfo2,
6888                               union spoolss_JobInfo **info_p,
6889                               uint32_t *count)
6890 {
6891         union spoolss_JobInfo *info;
6892         int i;
6893         WERROR result = WERR_OK;
6894
6895         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6896         W_ERROR_HAVE_NO_MEMORY(info);
6897
6898         *count = num_queues;
6899
6900         for (i=0; i<*count; i++) {
6901                 result = fill_job_info1(info,
6902                                         &info[i].info1,
6903                                         &queue[i],
6904                                         i,
6905                                         snum,
6906                                         pinfo2);
6907                 if (!W_ERROR_IS_OK(result)) {
6908                         goto out;
6909                 }
6910         }
6911
6912  out:
6913         if (!W_ERROR_IS_OK(result)) {
6914                 TALLOC_FREE(info);
6915                 *count = 0;
6916                 return result;
6917         }
6918
6919         *info_p = info;
6920
6921         return WERR_OK;
6922 }
6923
6924 /****************************************************************************
6925  Enumjobs at level 2.
6926 ****************************************************************************/
6927
6928 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6929                               const print_queue_struct *queue,
6930                               uint32_t num_queues, int snum,
6931                               struct spoolss_PrinterInfo2 *pinfo2,
6932                               union spoolss_JobInfo **info_p,
6933                               uint32_t *count)
6934 {
6935         union spoolss_JobInfo *info;
6936         int i;
6937         WERROR result = WERR_OK;
6938
6939         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6940         W_ERROR_HAVE_NO_MEMORY(info);
6941
6942         *count = num_queues;
6943
6944         for (i=0; i<*count; i++) {
6945                 struct spoolss_DeviceMode *devmode;
6946
6947                 result = spoolss_create_default_devmode(info,
6948                                                         pinfo2->printername,
6949                                                         &devmode);
6950                 if (!W_ERROR_IS_OK(result)) {
6951                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6952                         goto out;
6953                 }
6954
6955                 result = fill_job_info2(info,
6956                                         &info[i].info2,
6957                                         &queue[i],
6958                                         i,
6959                                         snum,
6960                                         pinfo2,
6961                                         devmode);
6962                 if (!W_ERROR_IS_OK(result)) {
6963                         goto out;
6964                 }
6965         }
6966
6967  out:
6968         if (!W_ERROR_IS_OK(result)) {
6969                 TALLOC_FREE(info);
6970                 *count = 0;
6971                 return result;
6972         }
6973
6974         *info_p = info;
6975
6976         return WERR_OK;
6977 }
6978
6979 /****************************************************************************
6980  Enumjobs at level 3.
6981 ****************************************************************************/
6982
6983 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6984                               const print_queue_struct *queue,
6985                               uint32_t num_queues, int snum,
6986                               struct spoolss_PrinterInfo2 *pinfo2,
6987                               union spoolss_JobInfo **info_p,
6988                               uint32_t *count)
6989 {
6990         union spoolss_JobInfo *info;
6991         int i;
6992         WERROR result = WERR_OK;
6993
6994         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6995         W_ERROR_HAVE_NO_MEMORY(info);
6996
6997         *count = num_queues;
6998
6999         for (i=0; i<*count; i++) {
7000                 const print_queue_struct *next_queue = NULL;
7001
7002                 if (i+1 < *count) {
7003                         next_queue = &queue[i+1];
7004                 }
7005
7006                 result = fill_job_info3(info,
7007                                         &info[i].info3,
7008                                         &queue[i],
7009                                         next_queue,
7010                                         i,
7011                                         snum,
7012                                         pinfo2);
7013                 if (!W_ERROR_IS_OK(result)) {
7014                         goto out;
7015                 }
7016         }
7017
7018  out:
7019         if (!W_ERROR_IS_OK(result)) {
7020                 TALLOC_FREE(info);
7021                 *count = 0;
7022                 return result;
7023         }
7024
7025         *info_p = info;
7026
7027         return WERR_OK;
7028 }
7029
7030 /****************************************************************
7031  _spoolss_EnumJobs
7032 ****************************************************************/
7033
7034 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7035                          struct spoolss_EnumJobs *r)
7036 {
7037         WERROR result;
7038         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7039         int snum;
7040         print_status_struct prt_status;
7041         print_queue_struct *queue = NULL;
7042         uint32_t count;
7043
7044         /* that's an [in out] buffer */
7045
7046         if (!r->in.buffer && (r->in.offered != 0)) {
7047                 return WERR_INVALID_PARAM;
7048         }
7049
7050         DEBUG(4,("_spoolss_EnumJobs\n"));
7051
7052         *r->out.needed = 0;
7053         *r->out.count = 0;
7054         *r->out.info = NULL;
7055
7056         /* lookup the printer snum and tdb entry */
7057
7058         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7059                 return WERR_BADFID;
7060         }
7061
7062         result = winreg_get_printer(p->mem_ctx,
7063                                     get_session_info_system(),
7064                                     p->msg_ctx,
7065                                     lp_const_servicename(snum),
7066                                     &pinfo2);
7067         if (!W_ERROR_IS_OK(result)) {
7068                 return result;
7069         }
7070
7071         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7072         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7073                 count, prt_status.status, prt_status.message));
7074
7075         if (count == 0) {
7076                 SAFE_FREE(queue);
7077                 TALLOC_FREE(pinfo2);
7078                 return WERR_OK;
7079         }
7080
7081         switch (r->in.level) {
7082         case 1:
7083                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7084                                          pinfo2, r->out.info, r->out.count);
7085                 break;
7086         case 2:
7087                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7088                                          pinfo2, r->out.info, r->out.count);
7089                 break;
7090         case 3:
7091                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7092                                          pinfo2, r->out.info, r->out.count);
7093                 break;
7094         default:
7095                 result = WERR_UNKNOWN_LEVEL;
7096                 break;
7097         }
7098
7099         SAFE_FREE(queue);
7100         TALLOC_FREE(pinfo2);
7101
7102         if (!W_ERROR_IS_OK(result)) {
7103                 return result;
7104         }
7105
7106         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7107                                                      spoolss_EnumJobs,
7108                                                      *r->out.info, r->in.level,
7109                                                      *r->out.count);
7110         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7111         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7112
7113         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7114 }
7115
7116 /****************************************************************
7117  _spoolss_ScheduleJob
7118 ****************************************************************/
7119
7120 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7121                             struct spoolss_ScheduleJob *r)
7122 {
7123         return WERR_OK;
7124 }
7125
7126 /****************************************************************
7127 ****************************************************************/
7128
7129 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7130                                struct messaging_context *msg_ctx,
7131                                const char *printer_name,
7132                                uint32_t job_id,
7133                                struct spoolss_SetJobInfo1 *r)
7134 {
7135         char *old_doc_name;
7136
7137         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7138                 return WERR_BADFID;
7139         }
7140
7141         if (strequal(old_doc_name, r->document_name)) {
7142                 return WERR_OK;
7143         }
7144
7145         if (!print_job_set_name(server_event_context(), msg_ctx,
7146                                 printer_name, job_id, r->document_name)) {
7147                 return WERR_BADFID;
7148         }
7149
7150         return WERR_OK;
7151 }
7152
7153 /****************************************************************
7154  _spoolss_SetJob
7155 ****************************************************************/
7156
7157 WERROR _spoolss_SetJob(struct pipes_struct *p,
7158                        struct spoolss_SetJob *r)
7159 {
7160         const struct auth_serversupplied_info *session_info = p->session_info;
7161         int snum;
7162         WERROR errcode = WERR_BADFUNC;
7163
7164         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7165                 return WERR_BADFID;
7166         }
7167
7168         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7169                 return WERR_INVALID_PRINTER_NAME;
7170         }
7171
7172         switch (r->in.command) {
7173         case SPOOLSS_JOB_CONTROL_CANCEL:
7174         case SPOOLSS_JOB_CONTROL_DELETE:
7175                 errcode = print_job_delete(session_info, p->msg_ctx,
7176                                            snum, r->in.job_id);
7177                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7178                         errcode = WERR_OK;
7179                 }
7180                 break;
7181         case SPOOLSS_JOB_CONTROL_PAUSE:
7182                 if (print_job_pause(session_info, p->msg_ctx,
7183                                     snum, r->in.job_id, &errcode)) {
7184                         errcode = WERR_OK;
7185                 }
7186                 break;
7187         case SPOOLSS_JOB_CONTROL_RESTART:
7188         case SPOOLSS_JOB_CONTROL_RESUME:
7189                 if (print_job_resume(session_info, p->msg_ctx,
7190                                      snum, r->in.job_id, &errcode)) {
7191                         errcode = WERR_OK;
7192                 }
7193                 break;
7194         case 0:
7195                 errcode = WERR_OK;
7196                 break;
7197         default:
7198                 return WERR_UNKNOWN_LEVEL;
7199         }
7200
7201         if (!W_ERROR_IS_OK(errcode)) {
7202                 return errcode;
7203         }
7204
7205         if (r->in.ctr == NULL) {
7206                 return errcode;
7207         }
7208
7209         switch (r->in.ctr->level) {
7210         case 1:
7211                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7212                                            lp_const_servicename(snum),
7213                                            r->in.job_id,
7214                                            r->in.ctr->info.info1);
7215                 break;
7216         case 2:
7217         case 3:
7218         case 4:
7219         default:
7220                 return WERR_UNKNOWN_LEVEL;
7221         }
7222
7223         return errcode;
7224 }
7225
7226 /****************************************************************************
7227  Enumerates all printer drivers by level and architecture.
7228 ****************************************************************************/
7229
7230 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7231                                                        const struct auth_serversupplied_info *session_info,
7232                                                        struct messaging_context *msg_ctx,
7233                                                        const char *servername,
7234                                                        const char *architecture,
7235                                                        uint32_t level,
7236                                                        union spoolss_DriverInfo **info_p,
7237                                                        uint32_t *count_p)
7238 {
7239         int i;
7240         uint32_t version;
7241         struct spoolss_DriverInfo8 *driver;
7242         union spoolss_DriverInfo *info = NULL;
7243         uint32_t count = 0;
7244         WERROR result = WERR_OK;
7245         uint32_t num_drivers;
7246         const char **drivers;
7247
7248         *count_p = 0;
7249         *info_p = NULL;
7250
7251         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7252                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7253                                                 architecture, version,
7254                                                 &num_drivers, &drivers);
7255                 if (!W_ERROR_IS_OK(result)) {
7256                         goto out;
7257                 }
7258                 DEBUG(4, ("we have:[%d] drivers in environment"
7259                           " [%s] and version [%d]\n",
7260                           num_drivers, architecture, version));
7261
7262                 if (num_drivers != 0) {
7263                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7264                                                     union spoolss_DriverInfo,
7265                                                     count + num_drivers);
7266                         if (!info) {
7267                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7268                                         "failed to enlarge driver info buffer!\n"));
7269                                 result = WERR_NOMEM;
7270                                 goto out;
7271                         }
7272                 }
7273
7274                 for (i = 0; i < num_drivers; i++) {
7275                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7276
7277                         result = winreg_get_driver(mem_ctx, session_info,
7278                                                    msg_ctx,
7279                                                    architecture, drivers[i],
7280                                                    version, &driver);
7281                         if (!W_ERROR_IS_OK(result)) {
7282                                 goto out;
7283                         }
7284
7285                         switch (level) {
7286                         case 1:
7287                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7288                                                                    driver, servername);
7289                                 break;
7290                         case 2:
7291                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7292                                                                    driver, servername);
7293                                 break;
7294                         case 3:
7295                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7296                                                                    driver, servername);
7297                                 break;
7298                         case 4:
7299                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7300                                                                    driver, servername);
7301                                 break;
7302                         case 5:
7303                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7304                                                                    driver, servername);
7305                                 break;
7306                         case 6:
7307                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7308                                                                    driver, servername);
7309                                 break;
7310                         case 8:
7311                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7312                                                                    driver, servername);
7313                                 break;
7314                         default:
7315                                 result = WERR_UNKNOWN_LEVEL;
7316                                 break;
7317                         }
7318
7319                         TALLOC_FREE(driver);
7320
7321                         if (!W_ERROR_IS_OK(result)) {
7322                                 goto out;
7323                         }
7324                 }
7325
7326                 count += num_drivers;
7327                 TALLOC_FREE(drivers);
7328         }
7329
7330  out:
7331         TALLOC_FREE(drivers);
7332
7333         if (!W_ERROR_IS_OK(result)) {
7334                 TALLOC_FREE(info);
7335                 return result;
7336         }
7337
7338         *info_p = info;
7339         *count_p = count;
7340
7341         return WERR_OK;
7342 }
7343
7344 /****************************************************************************
7345  Enumerates all printer drivers by level.
7346 ****************************************************************************/
7347
7348 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7349                                        const struct auth_serversupplied_info *session_info,
7350                                        struct messaging_context *msg_ctx,
7351                                        const char *servername,
7352                                        const char *architecture,
7353                                        uint32_t level,
7354                                        union spoolss_DriverInfo **info_p,
7355                                        uint32_t *count_p)
7356 {
7357         uint32_t a,i;
7358         WERROR result = WERR_OK;
7359
7360         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7361
7362                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7363
7364                         union spoolss_DriverInfo *info = NULL;
7365                         uint32_t count = 0;
7366
7367                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7368                                                                           session_info,
7369                                                                           msg_ctx,
7370                                                                           servername,
7371                                                                           archi_table[a].long_archi,
7372                                                                           level,
7373                                                                           &info,
7374                                                                           &count);
7375                         if (!W_ERROR_IS_OK(result)) {
7376                                 continue;
7377                         }
7378
7379                         for (i=0; i < count; i++) {
7380                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7381                                              info[i], info_p, count_p);
7382                         }
7383                 }
7384
7385                 return result;
7386         }
7387
7388         return enumprinterdrivers_level_by_architecture(mem_ctx,
7389                                                         session_info,
7390                                                         msg_ctx,
7391                                                         servername,
7392                                                         architecture,
7393                                                         level,
7394                                                         info_p,
7395                                                         count_p);
7396 }
7397
7398 /****************************************************************
7399  _spoolss_EnumPrinterDrivers
7400 ****************************************************************/
7401
7402 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7403                                    struct spoolss_EnumPrinterDrivers *r)
7404 {
7405         const char *cservername;
7406         WERROR result;
7407
7408         /* that's an [in out] buffer */
7409
7410         if (!r->in.buffer && (r->in.offered != 0)) {
7411                 return WERR_INVALID_PARAM;
7412         }
7413
7414         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7415
7416         *r->out.needed = 0;
7417         *r->out.count = 0;
7418         *r->out.info = NULL;
7419
7420         cservername = canon_servername(r->in.server);
7421
7422         if (!is_myname_or_ipaddr(cservername)) {
7423                 return WERR_UNKNOWN_PRINTER_DRIVER;
7424         }
7425
7426         result = enumprinterdrivers_level(p->mem_ctx,
7427                                           get_session_info_system(),
7428                                           p->msg_ctx,
7429                                           cservername,
7430                                           r->in.environment,
7431                                           r->in.level,
7432                                           r->out.info,
7433                                           r->out.count);
7434         if (!W_ERROR_IS_OK(result)) {
7435                 return result;
7436         }
7437
7438         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7439                                                      spoolss_EnumPrinterDrivers,
7440                                                      *r->out.info, r->in.level,
7441                                                      *r->out.count);
7442         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7443         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7444
7445         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7446 }
7447
7448 /****************************************************************
7449  _spoolss_EnumForms
7450 ****************************************************************/
7451
7452 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7453                           struct spoolss_EnumForms *r)
7454 {
7455         WERROR result;
7456
7457         *r->out.count = 0;
7458         *r->out.needed = 0;
7459         *r->out.info = NULL;
7460
7461         /* that's an [in out] buffer */
7462
7463         if (!r->in.buffer && (r->in.offered != 0) ) {
7464                 return WERR_INVALID_PARAM;
7465         }
7466
7467         DEBUG(4,("_spoolss_EnumForms\n"));
7468         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7469         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7470
7471         switch (r->in.level) {
7472         case 1:
7473                 result = winreg_printer_enumforms1(p->mem_ctx,
7474                                                    get_session_info_system(),
7475                                                    p->msg_ctx,
7476                                                    r->out.count,
7477                                                    r->out.info);
7478                 break;
7479         default:
7480                 result = WERR_UNKNOWN_LEVEL;
7481                 break;
7482         }
7483
7484         if (!W_ERROR_IS_OK(result)) {
7485                 return result;
7486         }
7487
7488         if (*r->out.count == 0) {
7489                 return WERR_NO_MORE_ITEMS;
7490         }
7491
7492         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7493                                                      spoolss_EnumForms,
7494                                                      *r->out.info, r->in.level,
7495                                                      *r->out.count);
7496         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7497         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7498
7499         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7500 }
7501
7502 /****************************************************************
7503  _spoolss_GetForm
7504 ****************************************************************/
7505
7506 WERROR _spoolss_GetForm(struct pipes_struct *p,
7507                         struct spoolss_GetForm *r)
7508 {
7509         WERROR result;
7510
7511         /* that's an [in out] buffer */
7512
7513         if (!r->in.buffer && (r->in.offered != 0)) {
7514                 return WERR_INVALID_PARAM;
7515         }
7516
7517         DEBUG(4,("_spoolss_GetForm\n"));
7518         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7519         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7520
7521         switch (r->in.level) {
7522         case 1:
7523                 result = winreg_printer_getform1(p->mem_ctx,
7524                                                  get_session_info_system(),
7525                                                  p->msg_ctx,
7526                                                  r->in.form_name,
7527                                                  &r->out.info->info1);
7528                 break;
7529         default:
7530                 result = WERR_UNKNOWN_LEVEL;
7531                 break;
7532         }
7533
7534         if (!W_ERROR_IS_OK(result)) {
7535                 TALLOC_FREE(r->out.info);
7536                 return result;
7537         }
7538
7539         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7540                                                r->out.info, r->in.level);
7541         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7542
7543         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7544 }
7545
7546 /****************************************************************************
7547 ****************************************************************************/
7548
7549 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7550                           struct spoolss_PortInfo1 *r,
7551                           const char *name)
7552 {
7553         r->port_name = talloc_strdup(mem_ctx, name);
7554         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7555
7556         return WERR_OK;
7557 }
7558
7559 /****************************************************************************
7560  TODO: This probably needs distinguish between TCP/IP and Local ports
7561  somehow.
7562 ****************************************************************************/
7563
7564 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7565                           struct spoolss_PortInfo2 *r,
7566                           const char *name)
7567 {
7568         r->port_name = talloc_strdup(mem_ctx, name);
7569         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7570
7571         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7572         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7573
7574         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7575         W_ERROR_HAVE_NO_MEMORY(r->description);
7576
7577         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7578         r->reserved = 0;
7579
7580         return WERR_OK;
7581 }
7582
7583
7584 /****************************************************************************
7585  wrapper around the enumer ports command
7586 ****************************************************************************/
7587
7588 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7589 {
7590         char *cmd = lp_enumports_cmd();
7591         char **qlines = NULL;
7592         char *command = NULL;
7593         int numlines;
7594         int ret;
7595         int fd;
7596
7597         *count = 0;
7598         *lines = NULL;
7599
7600         /* if no hook then just fill in the default port */
7601
7602         if ( !*cmd ) {
7603                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7604                         return WERR_NOMEM;
7605                 }
7606                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7607                         TALLOC_FREE(qlines);
7608                         return WERR_NOMEM;
7609                 }
7610                 qlines[1] = NULL;
7611                 numlines = 1;
7612         }
7613         else {
7614                 /* we have a valid enumport command */
7615
7616                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7617                 if (!command) {
7618                         return WERR_NOMEM;
7619                 }
7620
7621                 DEBUG(10,("Running [%s]\n", command));
7622                 ret = smbrun(command, &fd);
7623                 DEBUG(10,("Returned [%d]\n", ret));
7624                 TALLOC_FREE(command);
7625                 if (ret != 0) {
7626                         if (fd != -1) {
7627                                 close(fd);
7628                         }
7629                         return WERR_ACCESS_DENIED;
7630                 }
7631
7632                 numlines = 0;
7633                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7634                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7635                 close(fd);
7636         }
7637
7638         *count = numlines;
7639         *lines = qlines;
7640
7641         return WERR_OK;
7642 }
7643
7644 /****************************************************************************
7645  enumports level 1.
7646 ****************************************************************************/
7647
7648 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7649                                 union spoolss_PortInfo **info_p,
7650                                 uint32_t *count)
7651 {
7652         union spoolss_PortInfo *info = NULL;
7653         int i=0;
7654         WERROR result = WERR_OK;
7655         char **qlines = NULL;
7656         int numlines = 0;
7657
7658         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7659         if (!W_ERROR_IS_OK(result)) {
7660                 goto out;
7661         }
7662
7663         if (numlines) {
7664                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7665                 if (!info) {
7666                         DEBUG(10,("Returning WERR_NOMEM\n"));
7667                         result = WERR_NOMEM;
7668                         goto out;
7669                 }
7670
7671                 for (i=0; i<numlines; i++) {
7672                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7673                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7674                         if (!W_ERROR_IS_OK(result)) {
7675                                 goto out;
7676                         }
7677                 }
7678         }
7679         TALLOC_FREE(qlines);
7680
7681 out:
7682         if (!W_ERROR_IS_OK(result)) {
7683                 TALLOC_FREE(info);
7684                 TALLOC_FREE(qlines);
7685                 *count = 0;
7686                 *info_p = NULL;
7687                 return result;
7688         }
7689
7690         *info_p = info;
7691         *count = numlines;
7692
7693         return WERR_OK;
7694 }
7695
7696 /****************************************************************************
7697  enumports level 2.
7698 ****************************************************************************/
7699
7700 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7701                                 union spoolss_PortInfo **info_p,
7702                                 uint32_t *count)
7703 {
7704         union spoolss_PortInfo *info = NULL;
7705         int i=0;
7706         WERROR result = WERR_OK;
7707         char **qlines = NULL;
7708         int numlines = 0;
7709
7710         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7711         if (!W_ERROR_IS_OK(result)) {
7712                 goto out;
7713         }
7714
7715         if (numlines) {
7716                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7717                 if (!info) {
7718                         DEBUG(10,("Returning WERR_NOMEM\n"));
7719                         result = WERR_NOMEM;
7720                         goto out;
7721                 }
7722
7723                 for (i=0; i<numlines; i++) {
7724                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7725                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7726                         if (!W_ERROR_IS_OK(result)) {
7727                                 goto out;
7728                         }
7729                 }
7730         }
7731         TALLOC_FREE(qlines);
7732
7733 out:
7734         if (!W_ERROR_IS_OK(result)) {
7735                 TALLOC_FREE(info);
7736                 TALLOC_FREE(qlines);
7737                 *count = 0;
7738                 *info_p = NULL;
7739                 return result;
7740         }
7741
7742         *info_p = info;
7743         *count = numlines;
7744
7745         return WERR_OK;
7746 }
7747
7748 /****************************************************************
7749  _spoolss_EnumPorts
7750 ****************************************************************/
7751
7752 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7753                           struct spoolss_EnumPorts *r)
7754 {
7755         WERROR result;
7756
7757         /* that's an [in out] buffer */
7758
7759         if (!r->in.buffer && (r->in.offered != 0)) {
7760                 return WERR_INVALID_PARAM;
7761         }
7762
7763         DEBUG(4,("_spoolss_EnumPorts\n"));
7764
7765         *r->out.count = 0;
7766         *r->out.needed = 0;
7767         *r->out.info = NULL;
7768
7769         switch (r->in.level) {
7770         case 1:
7771                 result = enumports_level_1(p->mem_ctx, r->out.info,
7772                                            r->out.count);
7773                 break;
7774         case 2:
7775                 result = enumports_level_2(p->mem_ctx, r->out.info,
7776                                            r->out.count);
7777                 break;
7778         default:
7779                 return WERR_UNKNOWN_LEVEL;
7780         }
7781
7782         if (!W_ERROR_IS_OK(result)) {
7783                 return result;
7784         }
7785
7786         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7787                                                      spoolss_EnumPorts,
7788                                                      *r->out.info, r->in.level,
7789                                                      *r->out.count);
7790         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7791         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7792
7793         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7794 }
7795
7796 /****************************************************************************
7797 ****************************************************************************/
7798
7799 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7800                                            const char *server,
7801                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7802                                            struct spoolss_DeviceMode *devmode,
7803                                            struct security_descriptor *secdesc,
7804                                            struct spoolss_UserLevelCtr *user_ctr,
7805                                            struct policy_handle *handle)
7806 {
7807         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7808         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7809         int     snum;
7810         WERROR err = WERR_OK;
7811
7812         /* samba does not have a concept of local, non-shared printers yet, so
7813          * make sure we always setup sharename - gd */
7814         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7815             (info2->printername != NULL && info2->printername[0] != '\0')) {
7816                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7817                         "no sharename has been set, setting printername %s as sharename\n",
7818                         info2->printername));
7819                 info2->sharename = info2->printername;
7820         }
7821
7822         /* check to see if the printer already exists */
7823         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7824                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7825                         info2->sharename));
7826                 return WERR_PRINTER_ALREADY_EXISTS;
7827         }
7828
7829         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7830                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7831                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7832                                 info2->printername));
7833                         return WERR_PRINTER_ALREADY_EXISTS;
7834                 }
7835         }
7836
7837         /* validate printer info struct */
7838         if (!info2->printername || strlen(info2->printername) == 0) {
7839                 return WERR_INVALID_PRINTER_NAME;
7840         }
7841         if (!info2->portname || strlen(info2->portname) == 0) {
7842                 return WERR_UNKNOWN_PORT;
7843         }
7844         if (!info2->drivername || strlen(info2->drivername) == 0) {
7845                 return WERR_UNKNOWN_PRINTER_DRIVER;
7846         }
7847         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7848                 return WERR_UNKNOWN_PRINTPROCESSOR;
7849         }
7850
7851         /* FIXME!!!  smbd should check to see if the driver is installed before
7852            trying to add a printer like this  --jerry */
7853
7854         if (*lp_addprinter_cmd() ) {
7855                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7856                                        info2, p->client_id->addr,
7857                                        p->msg_ctx) ) {
7858                         return WERR_ACCESS_DENIED;
7859                 }
7860         } else {
7861                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7862                         "smb.conf parameter \"addprinter command\" is defined. This "
7863                         "parameter must exist for this call to succeed\n",
7864                         info2->sharename ));
7865         }
7866
7867         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7868                 return WERR_ACCESS_DENIED;
7869         }
7870
7871         /* you must be a printer admin to add a new printer */
7872         if (!print_access_check(p->session_info,
7873                                 p->msg_ctx,
7874                                 snum,
7875                                 PRINTER_ACCESS_ADMINISTER)) {
7876                 return WERR_ACCESS_DENIED;
7877         }
7878
7879         /*
7880          * Do sanity check on the requested changes for Samba.
7881          */
7882
7883         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7884                 return WERR_INVALID_PARAM;
7885         }
7886
7887         if (devmode == NULL) {
7888                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7889         }
7890
7891         update_dsspooler(p->mem_ctx,
7892                          get_session_info_system(),
7893                          p->msg_ctx,
7894                          0,
7895                          info2,
7896                          NULL);
7897
7898         err = winreg_update_printer(p->mem_ctx,
7899                                     get_session_info_system(),
7900                                     p->msg_ctx,
7901                                     info2->sharename,
7902                                     info2_mask,
7903                                     info2,
7904                                     devmode,
7905                                     secdesc);
7906         if (!W_ERROR_IS_OK(err)) {
7907                 return err;
7908         }
7909
7910         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7911         if (!W_ERROR_IS_OK(err)) {
7912                 /* Handle open failed - remove addition. */
7913                 ZERO_STRUCTP(handle);
7914                 return err;
7915         }
7916
7917         return WERR_OK;
7918 }
7919
7920 /****************************************************************
7921  _spoolss_AddPrinterEx
7922 ****************************************************************/
7923
7924 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7925                              struct spoolss_AddPrinterEx *r)
7926 {
7927         switch (r->in.info_ctr->level) {
7928         case 1:
7929                 /* we don't handle yet */
7930                 /* but I know what to do ... */
7931                 return WERR_UNKNOWN_LEVEL;
7932         case 2:
7933                 return spoolss_addprinterex_level_2(p, r->in.server,
7934                                                     r->in.info_ctr,
7935                                                     r->in.devmode_ctr->devmode,
7936                                                     r->in.secdesc_ctr->sd,
7937                                                     r->in.userlevel_ctr,
7938                                                     r->out.handle);
7939         default:
7940                 return WERR_UNKNOWN_LEVEL;
7941         }
7942 }
7943
7944 /****************************************************************
7945  _spoolss_AddPrinter
7946 ****************************************************************/
7947
7948 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7949                            struct spoolss_AddPrinter *r)
7950 {
7951         struct spoolss_AddPrinterEx a;
7952         struct spoolss_UserLevelCtr userlevel_ctr;
7953
7954         ZERO_STRUCT(userlevel_ctr);
7955
7956         userlevel_ctr.level = 1;
7957
7958         a.in.server             = r->in.server;
7959         a.in.info_ctr           = r->in.info_ctr;
7960         a.in.devmode_ctr        = r->in.devmode_ctr;
7961         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7962         a.in.userlevel_ctr      = &userlevel_ctr;
7963         a.out.handle            = r->out.handle;
7964
7965         return _spoolss_AddPrinterEx(p, &a);
7966 }
7967
7968 /****************************************************************
7969  _spoolss_AddPrinterDriverEx
7970 ****************************************************************/
7971
7972 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7973                                    struct spoolss_AddPrinterDriverEx *r)
7974 {
7975         WERROR err = WERR_OK;
7976         const char *driver_name = NULL;
7977         uint32_t version;
7978         const char *fn;
7979
7980         switch (p->opnum) {
7981                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7982                         fn = "_spoolss_AddPrinterDriver";
7983                         break;
7984                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7985                         fn = "_spoolss_AddPrinterDriverEx";
7986                         break;
7987                 default:
7988                         return WERR_INVALID_PARAM;
7989         }
7990
7991         /*
7992          * we only support the semantics of AddPrinterDriver()
7993          * i.e. only copy files that are newer than existing ones
7994          */
7995
7996         if (r->in.flags == 0) {
7997                 return WERR_INVALID_PARAM;
7998         }
7999
8000         if (r->in.flags != APD_COPY_NEW_FILES) {
8001                 return WERR_ACCESS_DENIED;
8002         }
8003
8004         /* FIXME */
8005         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8006                 /* Clever hack from Martin Zielinski <mz@seh.de>
8007                  * to allow downgrade from level 8 (Vista).
8008                  */
8009                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8010                         r->in.info_ctr->level));
8011                 return WERR_UNKNOWN_LEVEL;
8012         }
8013
8014         DEBUG(5,("Cleaning driver's information\n"));
8015         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8016         if (!W_ERROR_IS_OK(err))
8017                 goto done;
8018
8019         DEBUG(5,("Moving driver to final destination\n"));
8020         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8021         if (!W_ERROR_IS_OK(err)) {
8022                 goto done;
8023         }
8024
8025         err = winreg_add_driver(p->mem_ctx,
8026                                 get_session_info_system(),
8027                                 p->msg_ctx,
8028                                 r->in.info_ctr,
8029                                 &driver_name,
8030                                 &version);
8031         if (!W_ERROR_IS_OK(err)) {
8032                 goto done;
8033         }
8034
8035         /*
8036          * I think this is where he DrvUpgradePrinter() hook would be
8037          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8038          * server.  Right now, we just need to send ourselves a message
8039          * to update each printer bound to this driver.   --jerry
8040          */
8041
8042         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8043                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8044                         fn, driver_name));
8045         }
8046
8047 done:
8048         return err;
8049 }
8050
8051 /****************************************************************
8052  _spoolss_AddPrinterDriver
8053 ****************************************************************/
8054
8055 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8056                                  struct spoolss_AddPrinterDriver *r)
8057 {
8058         struct spoolss_AddPrinterDriverEx a;
8059
8060         switch (r->in.info_ctr->level) {
8061         case 2:
8062         case 3:
8063         case 4:
8064         case 5:
8065                 break;
8066         default:
8067                 return WERR_UNKNOWN_LEVEL;
8068         }
8069
8070         a.in.servername         = r->in.servername;
8071         a.in.info_ctr           = r->in.info_ctr;
8072         a.in.flags              = APD_COPY_NEW_FILES;
8073
8074         return _spoolss_AddPrinterDriverEx(p, &a);
8075 }
8076
8077 /****************************************************************************
8078 ****************************************************************************/
8079
8080 struct _spoolss_paths {
8081         int type;
8082         const char *share;
8083         const char *dir;
8084 };
8085
8086 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8087
8088 static const struct _spoolss_paths spoolss_paths[]= {
8089         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8090         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8091 };
8092
8093 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8094                                           const char *servername,
8095                                           const char *environment,
8096                                           int component,
8097                                           char **path)
8098 {
8099         const char *pservername = NULL;
8100         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8101         const char *short_archi;
8102
8103         *path = NULL;
8104
8105         /* environment may be empty */
8106         if (environment && strlen(environment)) {
8107                 long_archi = environment;
8108         }
8109
8110         /* servername may be empty */
8111         if (servername && strlen(servername)) {
8112                 pservername = canon_servername(servername);
8113
8114                 if (!is_myname_or_ipaddr(pservername)) {
8115                         return WERR_INVALID_PARAM;
8116                 }
8117         }
8118
8119         if (!(short_archi = get_short_archi(long_archi))) {
8120                 return WERR_INVALID_ENVIRONMENT;
8121         }
8122
8123         switch (component) {
8124         case SPOOLSS_PRTPROCS_PATH:
8125         case SPOOLSS_DRIVER_PATH:
8126                 if (pservername) {
8127                         *path = talloc_asprintf(mem_ctx,
8128                                         "\\\\%s\\%s\\%s",
8129                                         pservername,
8130                                         spoolss_paths[component].share,
8131                                         short_archi);
8132                 } else {
8133                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8134                                         SPOOLSS_DEFAULT_SERVER_PATH,
8135                                         spoolss_paths[component].dir,
8136                                         short_archi);
8137                 }
8138                 break;
8139         default:
8140                 return WERR_INVALID_PARAM;
8141         }
8142
8143         if (!*path) {
8144                 return WERR_NOMEM;
8145         }
8146
8147         return WERR_OK;
8148 }
8149
8150 /****************************************************************************
8151 ****************************************************************************/
8152
8153 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8154                                           const char *servername,
8155                                           const char *environment,
8156                                           struct spoolss_DriverDirectoryInfo1 *r)
8157 {
8158         WERROR werr;
8159         char *path = NULL;
8160
8161         werr = compose_spoolss_server_path(mem_ctx,
8162                                            servername,
8163                                            environment,
8164                                            SPOOLSS_DRIVER_PATH,
8165                                            &path);
8166         if (!W_ERROR_IS_OK(werr)) {
8167                 return werr;
8168         }
8169
8170         DEBUG(4,("printer driver directory: [%s]\n", path));
8171
8172         r->directory_name = path;
8173
8174         return WERR_OK;
8175 }
8176
8177 /****************************************************************
8178  _spoolss_GetPrinterDriverDirectory
8179 ****************************************************************/
8180
8181 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8182                                           struct spoolss_GetPrinterDriverDirectory *r)
8183 {
8184         WERROR werror;
8185
8186         /* that's an [in out] buffer */
8187
8188         if (!r->in.buffer && (r->in.offered != 0)) {
8189                 return WERR_INVALID_PARAM;
8190         }
8191
8192         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8193                 r->in.level));
8194
8195         *r->out.needed = 0;
8196
8197         /* r->in.level is ignored */
8198
8199         werror = getprinterdriverdir_level_1(p->mem_ctx,
8200                                              r->in.server,
8201                                              r->in.environment,
8202                                              &r->out.info->info1);
8203         if (!W_ERROR_IS_OK(werror)) {
8204                 TALLOC_FREE(r->out.info);
8205                 return werror;
8206         }
8207
8208         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8209                                                r->out.info, r->in.level);
8210         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8211
8212         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8213 }
8214
8215 /****************************************************************
8216  _spoolss_EnumPrinterData
8217 ****************************************************************/
8218
8219 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8220                                 struct spoolss_EnumPrinterData *r)
8221 {
8222         WERROR result;
8223         struct spoolss_EnumPrinterDataEx r2;
8224         uint32_t count;
8225         struct spoolss_PrinterEnumValues *info, *val = NULL;
8226         uint32_t needed;
8227
8228         r2.in.handle    = r->in.handle;
8229         r2.in.key_name  = "PrinterDriverData";
8230         r2.in.offered   = 0;
8231         r2.out.count    = &count;
8232         r2.out.info     = &info;
8233         r2.out.needed   = &needed;
8234
8235         result = _spoolss_EnumPrinterDataEx(p, &r2);
8236         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8237                 r2.in.offered = needed;
8238                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8239         }
8240         if (!W_ERROR_IS_OK(result)) {
8241                 return result;
8242         }
8243
8244         /*
8245          * The NT machine wants to know the biggest size of value and data
8246          *
8247          * cf: MSDN EnumPrinterData remark section
8248          */
8249
8250         if (!r->in.value_offered && !r->in.data_offered) {
8251                 uint32_t biggest_valuesize = 0;
8252                 uint32_t biggest_datasize = 0;
8253                 int i, name_length;
8254
8255                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8256
8257                 for (i=0; i<count; i++) {
8258
8259                         name_length = strlen(info[i].value_name);
8260                         if (strlen(info[i].value_name) > biggest_valuesize) {
8261                                 biggest_valuesize = name_length;
8262                         }
8263
8264                         if (info[i].data_length > biggest_datasize) {
8265                                 biggest_datasize = info[i].data_length;
8266                         }
8267
8268                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8269                                 biggest_datasize));
8270                 }
8271
8272                 /* the value is an UNICODE string but real_value_size is the length
8273                    in bytes including the trailing 0 */
8274
8275                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8276                 *r->out.data_needed  = biggest_datasize;
8277
8278                 DEBUG(6,("final values: [%d], [%d]\n",
8279                         *r->out.value_needed, *r->out.data_needed));
8280
8281                 return WERR_OK;
8282         }
8283
8284         if (r->in.enum_index < count) {
8285                 val = &info[r->in.enum_index];
8286         }
8287
8288         if (val == NULL) {
8289                 /* out_value should default to "" or else NT4 has
8290                    problems unmarshalling the response */
8291
8292                 if (r->in.value_offered) {
8293                         *r->out.value_needed = 1;
8294                         r->out.value_name = talloc_strdup(r, "");
8295                         if (!r->out.value_name) {
8296                                 return WERR_NOMEM;
8297                         }
8298                 } else {
8299                         r->out.value_name = NULL;
8300                         *r->out.value_needed = 0;
8301                 }
8302
8303                 /* the data is counted in bytes */
8304
8305                 *r->out.data_needed = r->in.data_offered;
8306
8307                 result = WERR_NO_MORE_ITEMS;
8308         } else {
8309                 /*
8310                  * the value is:
8311                  * - counted in bytes in the request
8312                  * - counted in UNICODE chars in the max reply
8313                  * - counted in bytes in the real size
8314                  *
8315                  * take a pause *before* coding not *during* coding
8316                  */
8317
8318                 /* name */
8319                 if (r->in.value_offered) {
8320                         r->out.value_name = talloc_strdup(r, val->value_name);
8321                         if (!r->out.value_name) {
8322                                 return WERR_NOMEM;
8323                         }
8324                         *r->out.value_needed = val->value_name_len;
8325                 } else {
8326                         r->out.value_name = NULL;
8327                         *r->out.value_needed = 0;
8328                 }
8329
8330                 /* type */
8331
8332                 *r->out.type = val->type;
8333
8334                 /* data - counted in bytes */
8335
8336                 /*
8337                  * See the section "Dynamically Typed Query Parameters"
8338                  * in MS-RPRN.
8339                  */
8340
8341                 if (r->out.data && val->data && val->data->data &&
8342                                 val->data_length && r->in.data_offered) {
8343                         memcpy(r->out.data, val->data->data,
8344                                 MIN(val->data_length,r->in.data_offered));
8345                 }
8346
8347                 *r->out.data_needed = val->data_length;
8348
8349                 result = WERR_OK;
8350         }
8351
8352         return result;
8353 }
8354
8355 /****************************************************************
8356  _spoolss_SetPrinterData
8357 ****************************************************************/
8358
8359 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8360                                struct spoolss_SetPrinterData *r)
8361 {
8362         struct spoolss_SetPrinterDataEx r2;
8363
8364         r2.in.handle            = r->in.handle;
8365         r2.in.key_name          = "PrinterDriverData";
8366         r2.in.value_name        = r->in.value_name;
8367         r2.in.type              = r->in.type;
8368         r2.in.data              = r->in.data;
8369         r2.in.offered           = r->in.offered;
8370
8371         return _spoolss_SetPrinterDataEx(p, &r2);
8372 }
8373
8374 /****************************************************************
8375  _spoolss_ResetPrinter
8376 ****************************************************************/
8377
8378 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8379                              struct spoolss_ResetPrinter *r)
8380 {
8381         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8382         int             snum;
8383
8384         DEBUG(5,("_spoolss_ResetPrinter\n"));
8385
8386         /*
8387          * All we do is to check to see if the handle and queue is valid.
8388          * This call really doesn't mean anything to us because we only
8389          * support RAW printing.   --jerry
8390          */
8391
8392         if (!Printer) {
8393                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8394                         OUR_HANDLE(r->in.handle)));
8395                 return WERR_BADFID;
8396         }
8397
8398         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8399                 return WERR_BADFID;
8400
8401
8402         /* blindly return success */
8403         return WERR_OK;
8404 }
8405
8406 /****************************************************************
8407  _spoolss_DeletePrinterData
8408 ****************************************************************/
8409
8410 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8411                                   struct spoolss_DeletePrinterData *r)
8412 {
8413         struct spoolss_DeletePrinterDataEx r2;
8414
8415         r2.in.handle            = r->in.handle;
8416         r2.in.key_name          = "PrinterDriverData";
8417         r2.in.value_name        = r->in.value_name;
8418
8419         return _spoolss_DeletePrinterDataEx(p, &r2);
8420 }
8421
8422 /****************************************************************
8423  _spoolss_AddForm
8424 ****************************************************************/
8425
8426 WERROR _spoolss_AddForm(struct pipes_struct *p,
8427                         struct spoolss_AddForm *r)
8428 {
8429         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8430         int snum = -1;
8431         WERROR status = WERR_OK;
8432
8433         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8434
8435         DEBUG(5,("_spoolss_AddForm\n"));
8436
8437         if (!Printer) {
8438                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8439                         OUR_HANDLE(r->in.handle)));
8440                 return WERR_BADFID;
8441         }
8442
8443         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8444            and not a printer admin, then fail */
8445
8446         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8447             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8448             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8449                                           p->session_info->info3->base.domain.string,
8450                                           NULL,
8451                                           p->session_info->security_token,
8452                                           lp_printer_admin(snum))) {
8453                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8454                 return WERR_ACCESS_DENIED;
8455         }
8456
8457         switch (form->flags) {
8458         case SPOOLSS_FORM_USER:
8459         case SPOOLSS_FORM_BUILTIN:
8460         case SPOOLSS_FORM_PRINTER:
8461                 break;
8462         default:
8463                 return WERR_INVALID_PARAM;
8464         }
8465
8466         status = winreg_printer_addform1(p->mem_ctx,
8467                                          get_session_info_system(),
8468                                          p->msg_ctx,
8469                                          form);
8470         if (!W_ERROR_IS_OK(status)) {
8471                 return status;
8472         }
8473
8474         /*
8475          * ChangeID must always be set if this is a printer
8476          */
8477         if (Printer->printer_type == SPLHND_PRINTER) {
8478                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8479                         return WERR_BADFID;
8480                 }
8481
8482                 status = winreg_printer_update_changeid(p->mem_ctx,
8483                                                         get_session_info_system(),
8484                                                         p->msg_ctx,
8485                                                         lp_const_servicename(snum));
8486                 if (!W_ERROR_IS_OK(status)) {
8487                         return status;
8488                 }
8489         }
8490
8491         return status;
8492 }
8493
8494 /****************************************************************
8495  _spoolss_DeleteForm
8496 ****************************************************************/
8497
8498 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8499                            struct spoolss_DeleteForm *r)
8500 {
8501         const char *form_name = r->in.form_name;
8502         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8503         int snum = -1;
8504         WERROR status = WERR_OK;
8505
8506         DEBUG(5,("_spoolss_DeleteForm\n"));
8507
8508         if (!Printer) {
8509                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8510                         OUR_HANDLE(r->in.handle)));
8511                 return WERR_BADFID;
8512         }
8513
8514         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8515             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8516             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8517                                           p->session_info->info3->base.domain.string,
8518                                           NULL,
8519                                           p->session_info->security_token,
8520                                           lp_printer_admin(snum))) {
8521                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8522                 return WERR_ACCESS_DENIED;
8523         }
8524
8525         status = winreg_printer_deleteform1(p->mem_ctx,
8526                                             get_session_info_system(),
8527                                             p->msg_ctx,
8528                                             form_name);
8529         if (!W_ERROR_IS_OK(status)) {
8530                 return status;
8531         }
8532
8533         /*
8534          * ChangeID must always be set if this is a printer
8535          */
8536         if (Printer->printer_type == SPLHND_PRINTER) {
8537                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8538                         return WERR_BADFID;
8539                 }
8540
8541                 status = winreg_printer_update_changeid(p->mem_ctx,
8542                                                         get_session_info_system(),
8543                                                         p->msg_ctx,
8544                                                         lp_const_servicename(snum));
8545                 if (!W_ERROR_IS_OK(status)) {
8546                         return status;
8547                 }
8548         }
8549
8550         return status;
8551 }
8552
8553 /****************************************************************
8554  _spoolss_SetForm
8555 ****************************************************************/
8556
8557 WERROR _spoolss_SetForm(struct pipes_struct *p,
8558                         struct spoolss_SetForm *r)
8559 {
8560         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8561         const char *form_name = r->in.form_name;
8562         int snum = -1;
8563         WERROR status = WERR_OK;
8564
8565         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8566
8567         DEBUG(5,("_spoolss_SetForm\n"));
8568
8569         if (!Printer) {
8570                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8571                         OUR_HANDLE(r->in.handle)));
8572                 return WERR_BADFID;
8573         }
8574
8575         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8576            and not a printer admin, then fail */
8577
8578         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8579              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8580              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8581                                           p->session_info->info3->base.domain.string,
8582                                           NULL,
8583                                           p->session_info->security_token,
8584                                           lp_printer_admin(snum))) {
8585                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8586                 return WERR_ACCESS_DENIED;
8587         }
8588
8589         status = winreg_printer_setform1(p->mem_ctx,
8590                                          get_session_info_system(),
8591                                          p->msg_ctx,
8592                                          form_name,
8593                                          form);
8594         if (!W_ERROR_IS_OK(status)) {
8595                 return status;
8596         }
8597
8598         /*
8599          * ChangeID must always be set if this is a printer
8600          */
8601         if (Printer->printer_type == SPLHND_PRINTER) {
8602                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8603                         return WERR_BADFID;
8604                 }
8605
8606                 status = winreg_printer_update_changeid(p->mem_ctx,
8607                                                         get_session_info_system(),
8608                                                         p->msg_ctx,
8609                                                         lp_const_servicename(snum));
8610                 if (!W_ERROR_IS_OK(status)) {
8611                         return status;
8612                 }
8613         }
8614
8615         return status;
8616 }
8617
8618 /****************************************************************************
8619  fill_print_processor1
8620 ****************************************************************************/
8621
8622 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8623                                     struct spoolss_PrintProcessorInfo1 *r,
8624                                     const char *print_processor_name)
8625 {
8626         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8627         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8628
8629         return WERR_OK;
8630 }
8631
8632 /****************************************************************************
8633  enumprintprocessors level 1.
8634 ****************************************************************************/
8635
8636 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8637                                           union spoolss_PrintProcessorInfo **info_p,
8638                                           uint32_t *count)
8639 {
8640         union spoolss_PrintProcessorInfo *info;
8641         WERROR result;
8642
8643         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8644         W_ERROR_HAVE_NO_MEMORY(info);
8645
8646         *count = 1;
8647
8648         result = fill_print_processor1(info, &info[0].info1, "winprint");
8649         if (!W_ERROR_IS_OK(result)) {
8650                 goto out;
8651         }
8652
8653  out:
8654         if (!W_ERROR_IS_OK(result)) {
8655                 TALLOC_FREE(info);
8656                 *count = 0;
8657                 return result;
8658         }
8659
8660         *info_p = info;
8661
8662         return WERR_OK;
8663 }
8664
8665 /****************************************************************
8666  _spoolss_EnumPrintProcessors
8667 ****************************************************************/
8668
8669 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8670                                     struct spoolss_EnumPrintProcessors *r)
8671 {
8672         WERROR result;
8673
8674         /* that's an [in out] buffer */
8675
8676         if (!r->in.buffer && (r->in.offered != 0)) {
8677                 return WERR_INVALID_PARAM;
8678         }
8679
8680         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8681
8682         /*
8683          * Enumerate the print processors ...
8684          *
8685          * Just reply with "winprint", to keep NT happy
8686          * and I can use my nice printer checker.
8687          */
8688
8689         *r->out.count = 0;
8690         *r->out.needed = 0;
8691         *r->out.info = NULL;
8692
8693         if (!get_short_archi(r->in.environment)) {
8694                 return WERR_INVALID_ENVIRONMENT;
8695         }
8696
8697         switch (r->in.level) {
8698         case 1:
8699                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8700                                                      r->out.count);
8701                 break;
8702         default:
8703                 return WERR_UNKNOWN_LEVEL;
8704         }
8705
8706         if (!W_ERROR_IS_OK(result)) {
8707                 return result;
8708         }
8709
8710         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8711                                                      spoolss_EnumPrintProcessors,
8712                                                      *r->out.info, r->in.level,
8713                                                      *r->out.count);
8714         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8715         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8716
8717         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8718 }
8719
8720 /****************************************************************************
8721  fill_printprocdatatype1
8722 ****************************************************************************/
8723
8724 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8725                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8726                                       const char *name_array)
8727 {
8728         r->name_array = talloc_strdup(mem_ctx, name_array);
8729         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8730
8731         return WERR_OK;
8732 }
8733
8734 /****************************************************************************
8735  enumprintprocdatatypes level 1.
8736 ****************************************************************************/
8737
8738 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8739                                              union spoolss_PrintProcDataTypesInfo **info_p,
8740                                              uint32_t *count)
8741 {
8742         WERROR result;
8743         union spoolss_PrintProcDataTypesInfo *info;
8744
8745         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8746         W_ERROR_HAVE_NO_MEMORY(info);
8747
8748         *count = 1;
8749
8750         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8751         if (!W_ERROR_IS_OK(result)) {
8752                 goto out;
8753         }
8754
8755  out:
8756         if (!W_ERROR_IS_OK(result)) {
8757                 TALLOC_FREE(info);
8758                 *count = 0;
8759                 return result;
8760         }
8761
8762         *info_p = info;
8763
8764         return WERR_OK;
8765 }
8766
8767 /****************************************************************
8768  _spoolss_EnumPrintProcDataTypes
8769 ****************************************************************/
8770
8771 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8772                                        struct spoolss_EnumPrintProcDataTypes *r)
8773 {
8774         WERROR result;
8775
8776         /* that's an [in out] buffer */
8777
8778         if (!r->in.buffer && (r->in.offered != 0)) {
8779                 return WERR_INVALID_PARAM;
8780         }
8781
8782         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8783
8784         *r->out.count = 0;
8785         *r->out.needed = 0;
8786         *r->out.info = NULL;
8787
8788         if (r->in.print_processor_name == NULL ||
8789             !strequal(r->in.print_processor_name, "winprint")) {
8790                 return WERR_UNKNOWN_PRINTPROCESSOR;
8791         }
8792
8793         switch (r->in.level) {
8794         case 1:
8795                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8796                                                         r->out.count);
8797                 break;
8798         default:
8799                 return WERR_UNKNOWN_LEVEL;
8800         }
8801
8802         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8803                                                      spoolss_EnumPrintProcDataTypes,
8804                                                      *r->out.info, r->in.level,
8805                                                      *r->out.count);
8806         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8807         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8808
8809         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8810 }
8811
8812 /****************************************************************************
8813  fill_monitor_1
8814 ****************************************************************************/
8815
8816 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8817                              struct spoolss_MonitorInfo1 *r,
8818                              const char *monitor_name)
8819 {
8820         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8821         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8822
8823         return WERR_OK;
8824 }
8825
8826 /****************************************************************************
8827  fill_monitor_2
8828 ****************************************************************************/
8829
8830 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8831                              struct spoolss_MonitorInfo2 *r,
8832                              const char *monitor_name,
8833                              const char *environment,
8834                              const char *dll_name)
8835 {
8836         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8837         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8838         r->environment                  = talloc_strdup(mem_ctx, environment);
8839         W_ERROR_HAVE_NO_MEMORY(r->environment);
8840         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8841         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8842
8843         return WERR_OK;
8844 }
8845
8846 /****************************************************************************
8847  enumprintmonitors level 1.
8848 ****************************************************************************/
8849
8850 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8851                                         union spoolss_MonitorInfo **info_p,
8852                                         uint32_t *count)
8853 {
8854         union spoolss_MonitorInfo *info;
8855         WERROR result = WERR_OK;
8856
8857         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8858         W_ERROR_HAVE_NO_MEMORY(info);
8859
8860         *count = 2;
8861
8862         result = fill_monitor_1(info, &info[0].info1,
8863                                 SPL_LOCAL_PORT);
8864         if (!W_ERROR_IS_OK(result)) {
8865                 goto out;
8866         }
8867
8868         result = fill_monitor_1(info, &info[1].info1,
8869                                 SPL_TCPIP_PORT);
8870         if (!W_ERROR_IS_OK(result)) {
8871                 goto out;
8872         }
8873
8874 out:
8875         if (!W_ERROR_IS_OK(result)) {
8876                 TALLOC_FREE(info);
8877                 *count = 0;
8878                 return result;
8879         }
8880
8881         *info_p = info;
8882
8883         return WERR_OK;
8884 }
8885
8886 /****************************************************************************
8887  enumprintmonitors level 2.
8888 ****************************************************************************/
8889
8890 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8891                                         union spoolss_MonitorInfo **info_p,
8892                                         uint32_t *count)
8893 {
8894         union spoolss_MonitorInfo *info;
8895         WERROR result = WERR_OK;
8896
8897         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8898         W_ERROR_HAVE_NO_MEMORY(info);
8899
8900         *count = 2;
8901
8902         result = fill_monitor_2(info, &info[0].info2,
8903                                 SPL_LOCAL_PORT,
8904                                 "Windows NT X86", /* FIXME */
8905                                 "localmon.dll");
8906         if (!W_ERROR_IS_OK(result)) {
8907                 goto out;
8908         }
8909
8910         result = fill_monitor_2(info, &info[1].info2,
8911                                 SPL_TCPIP_PORT,
8912                                 "Windows NT X86", /* FIXME */
8913                                 "tcpmon.dll");
8914         if (!W_ERROR_IS_OK(result)) {
8915                 goto out;
8916         }
8917
8918 out:
8919         if (!W_ERROR_IS_OK(result)) {
8920                 TALLOC_FREE(info);
8921                 *count = 0;
8922                 return result;
8923         }
8924
8925         *info_p = info;
8926
8927         return WERR_OK;
8928 }
8929
8930 /****************************************************************
8931  _spoolss_EnumMonitors
8932 ****************************************************************/
8933
8934 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8935                              struct spoolss_EnumMonitors *r)
8936 {
8937         WERROR result;
8938
8939         /* that's an [in out] buffer */
8940
8941         if (!r->in.buffer && (r->in.offered != 0)) {
8942                 return WERR_INVALID_PARAM;
8943         }
8944
8945         DEBUG(5,("_spoolss_EnumMonitors\n"));
8946
8947         /*
8948          * Enumerate the print monitors ...
8949          *
8950          * Just reply with "Local Port", to keep NT happy
8951          * and I can use my nice printer checker.
8952          */
8953
8954         *r->out.count = 0;
8955         *r->out.needed = 0;
8956         *r->out.info = NULL;
8957
8958         switch (r->in.level) {
8959         case 1:
8960                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8961                                                    r->out.count);
8962                 break;
8963         case 2:
8964                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8965                                                    r->out.count);
8966                 break;
8967         default:
8968                 return WERR_UNKNOWN_LEVEL;
8969         }
8970
8971         if (!W_ERROR_IS_OK(result)) {
8972                 return result;
8973         }
8974
8975         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8976                                                      spoolss_EnumMonitors,
8977                                                      *r->out.info, r->in.level,
8978                                                      *r->out.count);
8979         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8980         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8981
8982         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8983 }
8984
8985 /****************************************************************************
8986 ****************************************************************************/
8987
8988 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8989                              const print_queue_struct *queue,
8990                              int count, int snum,
8991                              struct spoolss_PrinterInfo2 *pinfo2,
8992                              uint32_t jobid,
8993                              struct spoolss_JobInfo1 *r)
8994 {
8995         int i = 0;
8996         bool found = false;
8997
8998         for (i=0; i<count; i++) {
8999                 if (queue[i].job == (int)jobid) {
9000                         found = true;
9001                         break;
9002                 }
9003         }
9004
9005         if (found == false) {
9006                 /* NT treats not found as bad param... yet another bad choice */
9007                 return WERR_INVALID_PARAM;
9008         }
9009
9010         return fill_job_info1(mem_ctx,
9011                               r,
9012                               &queue[i],
9013                               i,
9014                               snum,
9015                               pinfo2);
9016 }
9017
9018 /****************************************************************************
9019 ****************************************************************************/
9020
9021 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9022                              const print_queue_struct *queue,
9023                              int count, int snum,
9024                              struct spoolss_PrinterInfo2 *pinfo2,
9025                              uint32_t jobid,
9026                              struct spoolss_JobInfo2 *r)
9027 {
9028         int i = 0;
9029         bool found = false;
9030         struct spoolss_DeviceMode *devmode;
9031         WERROR result;
9032
9033         for (i=0; i<count; i++) {
9034                 if (queue[i].job == (int)jobid) {
9035                         found = true;
9036                         break;
9037                 }
9038         }
9039
9040         if (found == false) {
9041                 /* NT treats not found as bad param... yet another bad
9042                    choice */
9043                 return WERR_INVALID_PARAM;
9044         }
9045
9046         /*
9047          * if the print job does not have a DEVMODE associated with it,
9048          * just use the one for the printer. A NULL devicemode is not
9049          *  a failure condition
9050          */
9051
9052         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9053         if (!devmode) {
9054                 result = spoolss_create_default_devmode(mem_ctx,
9055                                                 pinfo2->printername,
9056                                                 &devmode);
9057                 if (!W_ERROR_IS_OK(result)) {
9058                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9059                         return result;
9060                 }
9061         }
9062
9063         return fill_job_info2(mem_ctx,
9064                               r,
9065                               &queue[i],
9066                               i,
9067                               snum,
9068                               pinfo2,
9069                               devmode);
9070 }
9071
9072 /****************************************************************
9073  _spoolss_GetJob
9074 ****************************************************************/
9075
9076 WERROR _spoolss_GetJob(struct pipes_struct *p,
9077                        struct spoolss_GetJob *r)
9078 {
9079         WERROR result = WERR_OK;
9080         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9081         int snum;
9082         int count;
9083         print_queue_struct      *queue = NULL;
9084         print_status_struct prt_status;
9085
9086         /* that's an [in out] buffer */
9087
9088         if (!r->in.buffer && (r->in.offered != 0)) {
9089                 return WERR_INVALID_PARAM;
9090         }
9091
9092         DEBUG(5,("_spoolss_GetJob\n"));
9093
9094         *r->out.needed = 0;
9095
9096         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9097                 return WERR_BADFID;
9098         }
9099
9100         result = winreg_get_printer(p->mem_ctx,
9101                                     get_session_info_system(),
9102                                     p->msg_ctx,
9103                                     lp_const_servicename(snum),
9104                                     &pinfo2);
9105         if (!W_ERROR_IS_OK(result)) {
9106                 return result;
9107         }
9108
9109         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9110
9111         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9112                      count, prt_status.status, prt_status.message));
9113
9114         switch (r->in.level) {
9115         case 1:
9116                 result = getjob_level_1(p->mem_ctx,
9117                                         queue, count, snum, pinfo2,
9118                                         r->in.job_id, &r->out.info->info1);
9119                 break;
9120         case 2:
9121                 result = getjob_level_2(p->mem_ctx,
9122                                         queue, count, snum, pinfo2,
9123                                         r->in.job_id, &r->out.info->info2);
9124                 break;
9125         default:
9126                 result = WERR_UNKNOWN_LEVEL;
9127                 break;
9128         }
9129
9130         SAFE_FREE(queue);
9131         TALLOC_FREE(pinfo2);
9132
9133         if (!W_ERROR_IS_OK(result)) {
9134                 TALLOC_FREE(r->out.info);
9135                 return result;
9136         }
9137
9138         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9139                                                                                    r->in.level);
9140         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9141
9142         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9143 }
9144
9145 /****************************************************************
9146  _spoolss_GetPrinterDataEx
9147 ****************************************************************/
9148
9149 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9150                                  struct spoolss_GetPrinterDataEx *r)
9151 {
9152
9153         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9154         const char *printer;
9155         int                     snum = 0;
9156         WERROR result = WERR_OK;
9157         DATA_BLOB blob;
9158         enum winreg_Type val_type;
9159         uint8_t *val_data;
9160         uint32_t val_size;
9161
9162
9163         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9164
9165         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9166                 r->in.key_name, r->in.value_name));
9167
9168         /* in case of problem, return some default values */
9169
9170         *r->out.needed  = 0;
9171         *r->out.type    = REG_NONE;
9172
9173         if (!Printer) {
9174                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9175                         OUR_HANDLE(r->in.handle)));
9176                 result = WERR_BADFID;
9177                 goto done;
9178         }
9179
9180         /* Is the handle to a printer or to the server? */
9181
9182         if (Printer->printer_type == SPLHND_SERVER) {
9183
9184                 union spoolss_PrinterData data;
9185
9186                 result = getprinterdata_printer_server(p->mem_ctx,
9187                                                        r->in.value_name,
9188                                                        r->out.type,
9189                                                        &data);
9190                 if (!W_ERROR_IS_OK(result)) {
9191                         return result;
9192                 }
9193
9194                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9195                                                   *r->out.type, &data);
9196                 if (!W_ERROR_IS_OK(result)) {
9197                         return result;
9198                 }
9199
9200                 *r->out.needed = blob.length;
9201
9202                 if (r->in.offered >= *r->out.needed) {
9203                         memcpy(r->out.data, blob.data, blob.length);
9204                 }
9205
9206                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9207         }
9208
9209         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9210                 return WERR_BADFID;
9211         }
9212         printer = lp_const_servicename(snum);
9213
9214         /* check to see if the keyname is valid */
9215         if (!strlen(r->in.key_name)) {
9216                 return WERR_INVALID_PARAM;
9217         }
9218
9219         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9220         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9221             strequal(r->in.value_name, "ChangeId")) {
9222                 *r->out.type = REG_DWORD;
9223                 *r->out.needed = 4;
9224                 if (r->in.offered >= *r->out.needed) {
9225                         uint32_t changeid = 0;
9226
9227                         result = winreg_printer_get_changeid(p->mem_ctx,
9228                                                              get_session_info_system(),
9229                                                              p->msg_ctx,
9230                                                              printer,
9231                                                              &changeid);
9232                         if (!W_ERROR_IS_OK(result)) {
9233                                 return result;
9234                         }
9235
9236                         SIVAL(r->out.data, 0, changeid);
9237                         result = WERR_OK;
9238                 }
9239                 goto done;
9240         }
9241
9242         result = winreg_get_printer_dataex(p->mem_ctx,
9243                                            get_session_info_system(),
9244                                            p->msg_ctx,
9245                                            printer,
9246                                            r->in.key_name,
9247                                            r->in.value_name,
9248                                            &val_type,
9249                                            &val_data,
9250                                            &val_size);
9251         if (!W_ERROR_IS_OK(result)) {
9252                 return result;
9253         }
9254
9255         *r->out.needed = val_size;
9256         *r->out.type = val_type;
9257
9258         if (r->in.offered >= *r->out.needed) {
9259                 memcpy(r->out.data, val_data, val_size);
9260         }
9261
9262  done:
9263         /* retain type when returning WERR_MORE_DATA */
9264         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9265
9266         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9267 }
9268
9269 /****************************************************************
9270  _spoolss_SetPrinterDataEx
9271 ****************************************************************/
9272
9273 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9274                                  struct spoolss_SetPrinterDataEx *r)
9275 {
9276         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9277         int                     snum = 0;
9278         WERROR                  result = WERR_OK;
9279         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9280         char                    *oid_string;
9281
9282         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9283
9284         /* From MSDN documentation of SetPrinterDataEx: pass request to
9285            SetPrinterData if key is "PrinterDriverData" */
9286
9287         if (!Printer) {
9288                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9289                         OUR_HANDLE(r->in.handle)));
9290                 return WERR_BADFID;
9291         }
9292
9293         if (Printer->printer_type == SPLHND_SERVER) {
9294                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9295                         "Not implemented for server handles yet\n"));
9296                 return WERR_INVALID_PARAM;
9297         }
9298
9299         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9300                 return WERR_BADFID;
9301         }
9302
9303         /*
9304          * Access check : NT returns "access denied" if you make a
9305          * SetPrinterData call without the necessary privildge.
9306          * we were originally returning OK if nothing changed
9307          * which made Win2k issue **a lot** of SetPrinterData
9308          * when connecting to a printer  --jerry
9309          */
9310
9311         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9312                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9313                         "change denied by handle access permissions\n"));
9314                 return WERR_ACCESS_DENIED;
9315         }
9316
9317         result = winreg_get_printer(Printer,
9318                                     get_session_info_system(),
9319                                     p->msg_ctx,
9320                                     lp_servicename(snum),
9321                                     &pinfo2);
9322         if (!W_ERROR_IS_OK(result)) {
9323                 return result;
9324         }
9325
9326         /* check for OID in valuename */
9327
9328         oid_string = strchr(r->in.value_name, ',');
9329         if (oid_string) {
9330                 *oid_string = '\0';
9331                 oid_string++;
9332         }
9333
9334         /* save the registry data */
9335
9336         result = winreg_set_printer_dataex(p->mem_ctx,
9337                                            get_session_info_system(),
9338                                            p->msg_ctx,
9339                                            pinfo2->sharename,
9340                                            r->in.key_name,
9341                                            r->in.value_name,
9342                                            r->in.type,
9343                                            r->in.data,
9344                                            r->in.offered);
9345
9346         if (W_ERROR_IS_OK(result)) {
9347                 /* save the OID if one was specified */
9348                 if (oid_string) {
9349                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9350                                 r->in.key_name, SPOOL_OID_KEY);
9351                         if (!str) {
9352                                 result = WERR_NOMEM;
9353                                 goto done;
9354                         }
9355
9356                         /*
9357                          * I'm not checking the status here on purpose.  Don't know
9358                          * if this is right, but I'm returning the status from the
9359                          * previous set_printer_dataex() call.  I have no idea if
9360                          * this is right.    --jerry
9361                          */
9362                         winreg_set_printer_dataex(p->mem_ctx,
9363                                                   get_session_info_system(),
9364                                                   p->msg_ctx,
9365                                                   pinfo2->sharename,
9366                                                   str,
9367                                                   r->in.value_name,
9368                                                   REG_SZ,
9369                                                   (uint8_t *) oid_string,
9370                                                   strlen(oid_string) + 1);
9371                 }
9372
9373                 result = winreg_printer_update_changeid(p->mem_ctx,
9374                                                         get_session_info_system(),
9375                                                         p->msg_ctx,
9376                                                         lp_const_servicename(snum));
9377
9378         }
9379
9380 done:
9381         talloc_free(pinfo2);
9382         return result;
9383 }
9384
9385 /****************************************************************
9386  _spoolss_DeletePrinterDataEx
9387 ****************************************************************/
9388
9389 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9390                                     struct spoolss_DeletePrinterDataEx *r)
9391 {
9392         const char *printer;
9393         int             snum=0;
9394         WERROR          status = WERR_OK;
9395         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9396
9397         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9398
9399         if (!Printer) {
9400                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9401                         "Invalid handle (%s:%u:%u).\n",
9402                         OUR_HANDLE(r->in.handle)));
9403                 return WERR_BADFID;
9404         }
9405
9406         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9407                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9408                         "printer properties change denied by handle\n"));
9409                 return WERR_ACCESS_DENIED;
9410         }
9411
9412         if (!r->in.value_name || !r->in.key_name) {
9413                 return WERR_NOMEM;
9414         }
9415
9416         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9417                 return WERR_BADFID;
9418         }
9419         printer = lp_const_servicename(snum);
9420
9421         status = winreg_delete_printer_dataex(p->mem_ctx,
9422                                               get_session_info_system(),
9423                                               p->msg_ctx,
9424                                               printer,
9425                                               r->in.key_name,
9426                                               r->in.value_name);
9427         if (W_ERROR_IS_OK(status)) {
9428                 status = winreg_printer_update_changeid(p->mem_ctx,
9429                                                         get_session_info_system(),
9430                                                         p->msg_ctx,
9431                                                         printer);
9432         }
9433
9434         return status;
9435 }
9436
9437 /****************************************************************
9438  _spoolss_EnumPrinterKey
9439 ****************************************************************/
9440
9441 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9442                                struct spoolss_EnumPrinterKey *r)
9443 {
9444         uint32_t        num_keys;
9445         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9446         int             snum = 0;
9447         WERROR          result = WERR_BADFILE;
9448         const char **array = NULL;
9449         DATA_BLOB blob;
9450
9451         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9452
9453         if (!Printer) {
9454                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9455                         OUR_HANDLE(r->in.handle)));
9456                 return WERR_BADFID;
9457         }
9458
9459         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9460                 return WERR_BADFID;
9461         }
9462
9463         result = winreg_enum_printer_key(p->mem_ctx,
9464                                          get_session_info_system(),
9465                                          p->msg_ctx,
9466                                          lp_const_servicename(snum),
9467                                          r->in.key_name,
9468                                          &num_keys,
9469                                          &array);
9470         if (!W_ERROR_IS_OK(result)) {
9471                 goto done;
9472         }
9473
9474         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9475                 result = WERR_NOMEM;
9476                 goto done;
9477         }
9478
9479         *r->out._ndr_size = r->in.offered / 2;
9480         *r->out.needed = blob.length;
9481
9482         if (r->in.offered < *r->out.needed) {
9483                 result = WERR_MORE_DATA;
9484         } else {
9485                 result = WERR_OK;
9486                 r->out.key_buffer->string_array = array;
9487         }
9488
9489  done:
9490         if (!W_ERROR_IS_OK(result)) {
9491                 TALLOC_FREE(array);
9492                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9493                         *r->out.needed = 0;
9494                 }
9495         }
9496
9497         return result;
9498 }
9499
9500 /****************************************************************
9501  _spoolss_DeletePrinterKey
9502 ****************************************************************/
9503
9504 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9505                                  struct spoolss_DeletePrinterKey *r)
9506 {
9507         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9508         int                     snum=0;
9509         WERROR                  status;
9510         const char *printer;
9511
9512         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9513
9514         if (!Printer) {
9515                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9516                         OUR_HANDLE(r->in.handle)));
9517                 return WERR_BADFID;
9518         }
9519
9520         /* if keyname == NULL, return error */
9521         if ( !r->in.key_name )
9522                 return WERR_INVALID_PARAM;
9523
9524         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9525                 return WERR_BADFID;
9526         }
9527
9528         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9529                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9530                         "printer properties change denied by handle\n"));
9531                 return WERR_ACCESS_DENIED;
9532         }
9533
9534         printer = lp_const_servicename(snum);
9535
9536         /* delete the key and all subkeys */
9537         status = winreg_delete_printer_key(p->mem_ctx,
9538                                            get_session_info_system(),
9539                                            p->msg_ctx,
9540                                            printer,
9541                                            r->in.key_name);
9542         if (W_ERROR_IS_OK(status)) {
9543                 status = winreg_printer_update_changeid(p->mem_ctx,
9544                                                         get_session_info_system(),
9545                                                         p->msg_ctx,
9546                                                         printer);
9547         }
9548
9549         return status;
9550 }
9551
9552 /****************************************************************
9553  _spoolss_EnumPrinterDataEx
9554 ****************************************************************/
9555
9556 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9557                                   struct spoolss_EnumPrinterDataEx *r)
9558 {
9559         uint32_t        count = 0;
9560         struct spoolss_PrinterEnumValues *info = NULL;
9561         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9562         int             snum;
9563         WERROR          result;
9564
9565         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9566
9567         *r->out.count = 0;
9568         *r->out.needed = 0;
9569         *r->out.info = NULL;
9570
9571         if (!Printer) {
9572                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9573                         OUR_HANDLE(r->in.handle)));
9574                 return WERR_BADFID;
9575         }
9576
9577         /*
9578          * first check for a keyname of NULL or "".  Win2k seems to send
9579          * this a lot and we should send back WERR_INVALID_PARAM
9580          * no need to spend time looking up the printer in this case.
9581          * --jerry
9582          */
9583
9584         if (!strlen(r->in.key_name)) {
9585                 result = WERR_INVALID_PARAM;
9586                 goto done;
9587         }
9588
9589         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9590                 return WERR_BADFID;
9591         }
9592
9593         /* now look for a match on the key name */
9594         result = winreg_enum_printer_dataex(p->mem_ctx,
9595                                             get_session_info_system(),
9596                                             p->msg_ctx,
9597                                             lp_const_servicename(snum),
9598                                             r->in.key_name,
9599                                             &count,
9600                                             &info);
9601         if (!W_ERROR_IS_OK(result)) {
9602                 goto done;
9603         }
9604
9605 #if 0 /* FIXME - gd */
9606         /* housekeeping information in the reply */
9607
9608         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9609          * the hand marshalled container size is a multiple
9610          * of 4 bytes for RPC alignment.
9611          */
9612
9613         if (needed % 4) {
9614                 needed += 4-(needed % 4);
9615         }
9616 #endif
9617         *r->out.count   = count;
9618         *r->out.info    = info;
9619
9620  done:
9621         if (!W_ERROR_IS_OK(result)) {
9622                 return result;
9623         }
9624
9625         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9626                                                spoolss_EnumPrinterDataEx,
9627                                                *r->out.info,
9628                                                *r->out.count);
9629         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9630         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9631
9632         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9633 }
9634
9635 /****************************************************************************
9636 ****************************************************************************/
9637
9638 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9639                                                  const char *servername,
9640                                                  const char *environment,
9641                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9642 {
9643         WERROR werr;
9644         char *path = NULL;
9645
9646         werr = compose_spoolss_server_path(mem_ctx,
9647                                            servername,
9648                                            environment,
9649                                            SPOOLSS_PRTPROCS_PATH,
9650                                            &path);
9651         if (!W_ERROR_IS_OK(werr)) {
9652                 return werr;
9653         }
9654
9655         DEBUG(4,("print processor directory: [%s]\n", path));
9656
9657         r->directory_name = path;
9658
9659         return WERR_OK;
9660 }
9661
9662 /****************************************************************
9663  _spoolss_GetPrintProcessorDirectory
9664 ****************************************************************/
9665
9666 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9667                                            struct spoolss_GetPrintProcessorDirectory *r)
9668 {
9669         WERROR result;
9670         char *prnproc_share = NULL;
9671         bool prnproc_share_exists = false;
9672         int snum;
9673
9674         /* that's an [in out] buffer */
9675
9676         if (!r->in.buffer && (r->in.offered != 0)) {
9677                 return WERR_INVALID_PARAM;
9678         }
9679
9680         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9681                 r->in.level));
9682
9683         *r->out.needed = 0;
9684
9685         /* r->in.level is ignored */
9686
9687         /* We always should reply with a local print processor directory so that
9688          * users are not forced to have a [prnproc$] share on the Samba spoolss
9689          * server, if users decide to do so, lets announce it though - Guenther */
9690
9691         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9692         if (!prnproc_share) {
9693                 return WERR_NOMEM;
9694         }
9695         if (snum != -1) {
9696                 prnproc_share_exists = true;
9697         }
9698
9699         result = getprintprocessordirectory_level_1(p->mem_ctx,
9700                                                     prnproc_share_exists ? r->in.server : NULL,
9701                                                     r->in.environment,
9702                                                     &r->out.info->info1);
9703         if (!W_ERROR_IS_OK(result)) {
9704                 TALLOC_FREE(r->out.info);
9705                 return result;
9706         }
9707
9708         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9709                                                                                    r->out.info, r->in.level);
9710         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9711
9712         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9713 }
9714
9715 /*******************************************************************
9716  ********************************************************************/
9717
9718 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9719                                const char *dllname)
9720 {
9721         enum ndr_err_code ndr_err;
9722         struct spoolss_MonitorUi ui;
9723
9724         ui.dll_name = dllname;
9725
9726         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9727                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9728         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9729                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9730         }
9731         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9732 }
9733
9734 /*******************************************************************
9735  Streams the monitor UI DLL name in UNICODE
9736 *******************************************************************/
9737
9738 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9739                                struct security_token *token, DATA_BLOB *in,
9740                                DATA_BLOB *out, uint32_t *needed)
9741 {
9742         const char *dllname = "tcpmonui.dll";
9743
9744         *needed = (strlen(dllname)+1) * 2;
9745
9746         if (out->length < *needed) {
9747                 return WERR_INSUFFICIENT_BUFFER;
9748         }
9749
9750         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9751                 return WERR_NOMEM;
9752         }
9753
9754         return WERR_OK;
9755 }
9756
9757 /*******************************************************************
9758  ********************************************************************/
9759
9760 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9761                              struct spoolss_PortData1 *port1,
9762                              const DATA_BLOB *buf)
9763 {
9764         enum ndr_err_code ndr_err;
9765         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9766                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9767         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9768                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9769         }
9770         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9771 }
9772
9773 /*******************************************************************
9774  ********************************************************************/
9775
9776 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9777                              struct spoolss_PortData2 *port2,
9778                              const DATA_BLOB *buf)
9779 {
9780         enum ndr_err_code ndr_err;
9781         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9782                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9783         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9784                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9785         }
9786         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9787 }
9788
9789 /*******************************************************************
9790  Create a new TCP/IP port
9791 *******************************************************************/
9792
9793 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9794                              struct security_token *token, DATA_BLOB *in,
9795                              DATA_BLOB *out, uint32_t *needed)
9796 {
9797         struct spoolss_PortData1 port1;
9798         struct spoolss_PortData2 port2;
9799         char *device_uri = NULL;
9800         uint32_t version;
9801
9802         const char *portname;
9803         const char *hostaddress;
9804         const char *queue;
9805         uint32_t port_number;
9806         uint32_t protocol;
9807
9808         /* peek for spoolss_PortData version */
9809
9810         if (!in || (in->length < (128 + 4))) {
9811                 return WERR_GENERAL_FAILURE;
9812         }
9813
9814         version = IVAL(in->data, 128);
9815
9816         switch (version) {
9817                 case 1:
9818                         ZERO_STRUCT(port1);
9819
9820                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9821                                 return WERR_NOMEM;
9822                         }
9823
9824                         portname        = port1.portname;
9825                         hostaddress     = port1.hostaddress;
9826                         queue           = port1.queue;
9827                         protocol        = port1.protocol;
9828                         port_number     = port1.port_number;
9829
9830                         break;
9831                 case 2:
9832                         ZERO_STRUCT(port2);
9833
9834                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9835                                 return WERR_NOMEM;
9836                         }
9837
9838                         portname        = port2.portname;
9839                         hostaddress     = port2.hostaddress;
9840                         queue           = port2.queue;
9841                         protocol        = port2.protocol;
9842                         port_number     = port2.port_number;
9843
9844                         break;
9845                 default:
9846                         DEBUG(1,("xcvtcp_addport: "
9847                                 "unknown version of port_data: %d\n", version));
9848                         return WERR_UNKNOWN_PORT;
9849         }
9850
9851         /* create the device URI and call the add_port_hook() */
9852
9853         switch (protocol) {
9854         case PROTOCOL_RAWTCP_TYPE:
9855                 device_uri = talloc_asprintf(mem_ctx,
9856                                 "socket://%s:%d/", hostaddress,
9857                                 port_number);
9858                 break;
9859
9860         case PROTOCOL_LPR_TYPE:
9861                 device_uri = talloc_asprintf(mem_ctx,
9862                         "lpr://%s/%s", hostaddress, queue );
9863                 break;
9864
9865         default:
9866                 return WERR_UNKNOWN_PORT;
9867         }
9868
9869         if (!device_uri) {
9870                 return WERR_NOMEM;
9871         }
9872
9873         return add_port_hook(mem_ctx, token, portname, device_uri);
9874 }
9875
9876 /*******************************************************************
9877 *******************************************************************/
9878
9879 struct xcv_api_table xcvtcp_cmds[] = {
9880         { "MonitorUI",  xcvtcp_monitorui },
9881         { "AddPort",    xcvtcp_addport},
9882         { NULL,         NULL }
9883 };
9884
9885 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9886                                      struct security_token *token, const char *command,
9887                                      DATA_BLOB *inbuf,
9888                                      DATA_BLOB *outbuf,
9889                                      uint32_t *needed )
9890 {
9891         int i;
9892
9893         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9894
9895         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9896                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9897                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9898         }
9899
9900         return WERR_BADFUNC;
9901 }
9902
9903 /*******************************************************************
9904 *******************************************************************/
9905 #if 0   /* don't support management using the "Local Port" monitor */
9906
9907 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9908                                  struct security_token *token, DATA_BLOB *in,
9909                                  DATA_BLOB *out, uint32_t *needed)
9910 {
9911         const char *dllname = "localui.dll";
9912
9913         *needed = (strlen(dllname)+1) * 2;
9914
9915         if (out->length < *needed) {
9916                 return WERR_INSUFFICIENT_BUFFER;
9917         }
9918
9919         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9920                 return WERR_NOMEM;
9921         }
9922
9923         return WERR_OK;
9924 }
9925
9926 /*******************************************************************
9927 *******************************************************************/
9928
9929 struct xcv_api_table xcvlocal_cmds[] = {
9930         { "MonitorUI",  xcvlocal_monitorui },
9931         { NULL,         NULL }
9932 };
9933 #else
9934 struct xcv_api_table xcvlocal_cmds[] = {
9935         { NULL,         NULL }
9936 };
9937 #endif
9938
9939
9940
9941 /*******************************************************************
9942 *******************************************************************/
9943
9944 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9945                                        struct security_token *token, const char *command,
9946                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9947                                        uint32_t *needed)
9948 {
9949         int i;
9950
9951         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9952
9953         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9954                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9955                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9956         }
9957         return WERR_BADFUNC;
9958 }
9959
9960 /****************************************************************
9961  _spoolss_XcvData
9962 ****************************************************************/
9963
9964 WERROR _spoolss_XcvData(struct pipes_struct *p,
9965                         struct spoolss_XcvData *r)
9966 {
9967         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9968         DATA_BLOB out_data = data_blob_null;
9969         WERROR werror;
9970
9971         if (!Printer) {
9972                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9973                         OUR_HANDLE(r->in.handle)));
9974                 return WERR_BADFID;
9975         }
9976
9977         /* Has to be a handle to the TCP/IP port monitor */
9978
9979         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9980                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9981                 return WERR_BADFID;
9982         }
9983
9984         /* requires administrative access to the server */
9985
9986         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9987                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9988                 return WERR_ACCESS_DENIED;
9989         }
9990
9991         /* Allocate the outgoing buffer */
9992
9993         if (r->in.out_data_size) {
9994                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9995                 if (out_data.data == NULL) {
9996                         return WERR_NOMEM;
9997                 }
9998         }
9999
10000         switch ( Printer->printer_type ) {
10001         case SPLHND_PORTMON_TCP:
10002                 werror = process_xcvtcp_command(p->mem_ctx,
10003                                                 p->session_info->security_token,
10004                                                 r->in.function_name,
10005                                                 &r->in.in_data, &out_data,
10006                                                 r->out.needed);
10007                 break;
10008         case SPLHND_PORTMON_LOCAL:
10009                 werror = process_xcvlocal_command(p->mem_ctx,
10010                                                   p->session_info->security_token,
10011                                                   r->in.function_name,
10012                                                   &r->in.in_data, &out_data,
10013                                                   r->out.needed);
10014                 break;
10015         default:
10016                 werror = WERR_INVALID_PRINT_MONITOR;
10017         }
10018
10019         if (!W_ERROR_IS_OK(werror)) {
10020                 return werror;
10021         }
10022
10023         *r->out.status_code = 0;
10024
10025         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10026                 memcpy(r->out.out_data, out_data.data,
10027                         MIN(r->in.out_data_size, out_data.length));
10028         }
10029
10030         return WERR_OK;
10031 }
10032
10033 /****************************************************************
10034  _spoolss_AddPrintProcessor
10035 ****************************************************************/
10036
10037 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10038                                   struct spoolss_AddPrintProcessor *r)
10039 {
10040         /* for now, just indicate success and ignore the add.  We'll
10041            automatically set the winprint processor for printer
10042            entries later.  Used to debug the LexMark Optra S 1855 PCL
10043            driver --jerry */
10044
10045         return WERR_OK;
10046 }
10047
10048 /****************************************************************
10049  _spoolss_AddPort
10050 ****************************************************************/
10051
10052 WERROR _spoolss_AddPort(struct pipes_struct *p,
10053                         struct spoolss_AddPort *r)
10054 {
10055         /* do what w2k3 does */
10056
10057         return WERR_NOT_SUPPORTED;
10058 }
10059
10060 /****************************************************************
10061  _spoolss_GetPrinterDriver
10062 ****************************************************************/
10063
10064 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10065                                  struct spoolss_GetPrinterDriver *r)
10066 {
10067         p->rng_fault_state = true;
10068         return WERR_NOT_SUPPORTED;
10069 }
10070
10071 /****************************************************************
10072  _spoolss_ReadPrinter
10073 ****************************************************************/
10074
10075 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10076                             struct spoolss_ReadPrinter *r)
10077 {
10078         p->rng_fault_state = true;
10079         return WERR_NOT_SUPPORTED;
10080 }
10081
10082 /****************************************************************
10083  _spoolss_WaitForPrinterChange
10084 ****************************************************************/
10085
10086 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10087                                      struct spoolss_WaitForPrinterChange *r)
10088 {
10089         p->rng_fault_state = true;
10090         return WERR_NOT_SUPPORTED;
10091 }
10092
10093 /****************************************************************
10094  _spoolss_ConfigurePort
10095 ****************************************************************/
10096
10097 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10098                               struct spoolss_ConfigurePort *r)
10099 {
10100         p->rng_fault_state = true;
10101         return WERR_NOT_SUPPORTED;
10102 }
10103
10104 /****************************************************************
10105  _spoolss_DeletePort
10106 ****************************************************************/
10107
10108 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10109                            struct spoolss_DeletePort *r)
10110 {
10111         p->rng_fault_state = true;
10112         return WERR_NOT_SUPPORTED;
10113 }
10114
10115 /****************************************************************
10116  _spoolss_CreatePrinterIC
10117 ****************************************************************/
10118
10119 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10120                                 struct spoolss_CreatePrinterIC *r)
10121 {
10122         p->rng_fault_state = true;
10123         return WERR_NOT_SUPPORTED;
10124 }
10125
10126 /****************************************************************
10127  _spoolss_PlayGDIScriptOnPrinterIC
10128 ****************************************************************/
10129
10130 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10131                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10132 {
10133         p->rng_fault_state = true;
10134         return WERR_NOT_SUPPORTED;
10135 }
10136
10137 /****************************************************************
10138  _spoolss_DeletePrinterIC
10139 ****************************************************************/
10140
10141 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10142                                 struct spoolss_DeletePrinterIC *r)
10143 {
10144         p->rng_fault_state = true;
10145         return WERR_NOT_SUPPORTED;
10146 }
10147
10148 /****************************************************************
10149  _spoolss_AddPrinterConnection
10150 ****************************************************************/
10151
10152 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10153                                      struct spoolss_AddPrinterConnection *r)
10154 {
10155         p->rng_fault_state = true;
10156         return WERR_NOT_SUPPORTED;
10157 }
10158
10159 /****************************************************************
10160  _spoolss_DeletePrinterConnection
10161 ****************************************************************/
10162
10163 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10164                                         struct spoolss_DeletePrinterConnection *r)
10165 {
10166         p->rng_fault_state = true;
10167         return WERR_NOT_SUPPORTED;
10168 }
10169
10170 /****************************************************************
10171  _spoolss_PrinterMessageBox
10172 ****************************************************************/
10173
10174 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10175                                   struct spoolss_PrinterMessageBox *r)
10176 {
10177         p->rng_fault_state = true;
10178         return WERR_NOT_SUPPORTED;
10179 }
10180
10181 /****************************************************************
10182  _spoolss_AddMonitor
10183 ****************************************************************/
10184
10185 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10186                            struct spoolss_AddMonitor *r)
10187 {
10188         p->rng_fault_state = true;
10189         return WERR_NOT_SUPPORTED;
10190 }
10191
10192 /****************************************************************
10193  _spoolss_DeleteMonitor
10194 ****************************************************************/
10195
10196 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10197                               struct spoolss_DeleteMonitor *r)
10198 {
10199         p->rng_fault_state = true;
10200         return WERR_NOT_SUPPORTED;
10201 }
10202
10203 /****************************************************************
10204  _spoolss_DeletePrintProcessor
10205 ****************************************************************/
10206
10207 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10208                                      struct spoolss_DeletePrintProcessor *r)
10209 {
10210         p->rng_fault_state = true;
10211         return WERR_NOT_SUPPORTED;
10212 }
10213
10214 /****************************************************************
10215  _spoolss_AddPrintProvidor
10216 ****************************************************************/
10217
10218 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10219                                  struct spoolss_AddPrintProvidor *r)
10220 {
10221         p->rng_fault_state = true;
10222         return WERR_NOT_SUPPORTED;
10223 }
10224
10225 /****************************************************************
10226  _spoolss_DeletePrintProvidor
10227 ****************************************************************/
10228
10229 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10230                                     struct spoolss_DeletePrintProvidor *r)
10231 {
10232         p->rng_fault_state = true;
10233         return WERR_NOT_SUPPORTED;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_FindFirstPrinterChangeNotification
10238 ****************************************************************/
10239
10240 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10241                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10242 {
10243         p->rng_fault_state = true;
10244         return WERR_NOT_SUPPORTED;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_FindNextPrinterChangeNotification
10249 ****************************************************************/
10250
10251 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10252                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10253 {
10254         p->rng_fault_state = true;
10255         return WERR_NOT_SUPPORTED;
10256 }
10257
10258 /****************************************************************
10259  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10260 ****************************************************************/
10261
10262 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10263                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10264 {
10265         p->rng_fault_state = true;
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_ReplyOpenPrinter
10271 ****************************************************************/
10272
10273 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10274                                  struct spoolss_ReplyOpenPrinter *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_RouterReplyPrinter
10282 ****************************************************************/
10283
10284 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10285                                    struct spoolss_RouterReplyPrinter *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_ReplyClosePrinter
10293 ****************************************************************/
10294
10295 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10296                                   struct spoolss_ReplyClosePrinter *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_AddPortEx
10304 ****************************************************************/
10305
10306 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10307                           struct spoolss_AddPortEx *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_RouterFindFirstPrinterChangeNotification
10315 ****************************************************************/
10316
10317 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10318                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_SpoolerInit
10326 ****************************************************************/
10327
10328 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10329                             struct spoolss_SpoolerInit *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_ResetPrinterEx
10337 ****************************************************************/
10338
10339 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10340                                struct spoolss_ResetPrinterEx *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_RouterReplyPrinterEx
10348 ****************************************************************/
10349
10350 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10351                                      struct spoolss_RouterReplyPrinterEx *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_44
10359 ****************************************************************/
10360
10361 WERROR _spoolss_44(struct pipes_struct *p,
10362                    struct spoolss_44 *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_SetPort
10370 ****************************************************************/
10371
10372 WERROR _spoolss_SetPort(struct pipes_struct *p,
10373                         struct spoolss_SetPort *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_4a
10381 ****************************************************************/
10382
10383 WERROR _spoolss_4a(struct pipes_struct *p,
10384                    struct spoolss_4a *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_4b
10392 ****************************************************************/
10393
10394 WERROR _spoolss_4b(struct pipes_struct *p,
10395                    struct spoolss_4b *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_4c
10403 ****************************************************************/
10404
10405 WERROR _spoolss_4c(struct pipes_struct *p,
10406                    struct spoolss_4c *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_53
10414 ****************************************************************/
10415
10416 WERROR _spoolss_53(struct pipes_struct *p,
10417                    struct spoolss_53 *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_AddPerMachineConnection
10425 ****************************************************************/
10426
10427 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10428                                         struct spoolss_AddPerMachineConnection *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_DeletePerMachineConnection
10436 ****************************************************************/
10437
10438 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10439                                            struct spoolss_DeletePerMachineConnection *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_EnumPerMachineConnections
10447 ****************************************************************/
10448
10449 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10450                                           struct spoolss_EnumPerMachineConnections *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_5a
10458 ****************************************************************/
10459
10460 WERROR _spoolss_5a(struct pipes_struct *p,
10461                    struct spoolss_5a *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_5b
10469 ****************************************************************/
10470
10471 WERROR _spoolss_5b(struct pipes_struct *p,
10472                    struct spoolss_5b *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_5c
10480 ****************************************************************/
10481
10482 WERROR _spoolss_5c(struct pipes_struct *p,
10483                    struct spoolss_5c *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_5d
10491 ****************************************************************/
10492
10493 WERROR _spoolss_5d(struct pipes_struct *p,
10494                    struct spoolss_5d *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_5e
10502 ****************************************************************/
10503
10504 WERROR _spoolss_5e(struct pipes_struct *p,
10505                    struct spoolss_5e *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_5f
10513 ****************************************************************/
10514
10515 WERROR _spoolss_5f(struct pipes_struct *p,
10516                    struct spoolss_5f *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_60
10524 ****************************************************************/
10525
10526 WERROR _spoolss_60(struct pipes_struct *p,
10527                    struct spoolss_60 *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_61
10535 ****************************************************************/
10536
10537 WERROR _spoolss_61(struct pipes_struct *p,
10538                    struct spoolss_61 *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_62
10546 ****************************************************************/
10547
10548 WERROR _spoolss_62(struct pipes_struct *p,
10549                    struct spoolss_62 *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_63
10557 ****************************************************************/
10558
10559 WERROR _spoolss_63(struct pipes_struct *p,
10560                    struct spoolss_63 *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_64
10568 ****************************************************************/
10569
10570 WERROR _spoolss_64(struct pipes_struct *p,
10571                    struct spoolss_64 *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_65
10579 ****************************************************************/
10580
10581 WERROR _spoolss_65(struct pipes_struct *p,
10582                    struct spoolss_65 *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_GetCorePrinterDrivers
10590 ****************************************************************/
10591
10592 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10593                                       struct spoolss_GetCorePrinterDrivers *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_67
10601 ****************************************************************/
10602
10603 WERROR _spoolss_67(struct pipes_struct *p,
10604                    struct spoolss_67 *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_GetPrinterDriverPackagePath
10612 ****************************************************************/
10613
10614 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10615                                             struct spoolss_GetPrinterDriverPackagePath *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_69
10623 ****************************************************************/
10624
10625 WERROR _spoolss_69(struct pipes_struct *p,
10626                    struct spoolss_69 *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_6a
10634 ****************************************************************/
10635
10636 WERROR _spoolss_6a(struct pipes_struct *p,
10637                    struct spoolss_6a *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_6b
10645 ****************************************************************/
10646
10647 WERROR _spoolss_6b(struct pipes_struct *p,
10648                    struct spoolss_6b *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_6c
10656 ****************************************************************/
10657
10658 WERROR _spoolss_6c(struct pipes_struct *p,
10659                    struct spoolss_6c *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_6d
10667 ****************************************************************/
10668
10669 WERROR _spoolss_6d(struct pipes_struct *p,
10670                    struct spoolss_6d *r)
10671 {
10672         p->rng_fault_state = true;
10673         return WERR_NOT_SUPPORTED;
10674 }