56a27134421c96061049ba3a6735ea0859322a4e
[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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "librpc/gen_ndr/messaging.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
50 /* macros stolen from s4 spoolss server */
51 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
52         ((info)?ndr_size_##fn(info, level, 0):0)
53
54 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
55         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
56
57 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
58         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
59
60 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
61
62 #undef DBGC_CLASS
63 #define DBGC_CLASS DBGC_RPC_SRV
64
65 #ifndef MAX_OPEN_PRINTER_EXS
66 #define MAX_OPEN_PRINTER_EXS 50
67 #endif
68
69 struct notify_back_channel;
70
71 /* structure to store the printer handles */
72 /* and a reference to what it's pointing to */
73 /* and the notify info asked about */
74 /* that's the central struct */
75 struct printer_handle {
76         struct printer_handle *prev, *next;
77         bool document_started;
78         bool page_started;
79         uint32 jobid; /* jobid in printing backend */
80         int printer_type;
81         const char *servername;
82         fstring sharename;
83         uint32 type;
84         uint32 access_granted;
85         struct {
86                 uint32 flags;
87                 uint32 options;
88                 fstring localmachine;
89                 uint32 printerlocal;
90                 struct spoolss_NotifyOption *option;
91                 struct policy_handle cli_hnd;
92                 struct notify_back_channel *cli_chan;
93                 uint32 change;
94                 /* are we in a FindNextPrinterChangeNotify() call? */
95                 bool fnpcn;
96                 struct messaging_context *msg_ctx;
97         } notify;
98         struct {
99                 fstring machine;
100                 fstring user;
101         } client;
102
103         /* devmode sent in the OpenPrinter() call */
104         struct spoolss_DeviceMode *devmode;
105
106         /* TODO cache the printer info2 structure */
107         struct spoolss_PrinterInfo2 *info2;
108
109 };
110
111 static struct printer_handle *printers_list;
112
113 struct printer_session_counter {
114         struct printer_session_counter *next;
115         struct printer_session_counter *prev;
116
117         int snum;
118         uint32_t counter;
119 };
120
121 static struct printer_session_counter *counter_list;
122
123 struct notify_back_channel {
124         struct notify_back_channel *prev, *next;
125
126         /* associated client */
127         struct sockaddr_storage client_address;
128
129         /* print notify back-channel pipe handle*/
130         struct rpc_pipe_client *cli_pipe;
131         struct dcerpc_binding_handle *binding_handle;
132         uint32_t active_connections;
133 };
134
135 static struct notify_back_channel *back_channels;
136
137 /* Map generic permissions to printer object specific permissions */
138
139 const struct standard_mapping printer_std_mapping = {
140         PRINTER_READ,
141         PRINTER_WRITE,
142         PRINTER_EXECUTE,
143         PRINTER_ALL_ACCESS
144 };
145
146 /* Map generic permissions to print server object specific permissions */
147
148 const struct standard_mapping printserver_std_mapping = {
149         SERVER_READ,
150         SERVER_WRITE,
151         SERVER_EXECUTE,
152         SERVER_ALL_ACCESS
153 };
154
155 /* API table for Xcv Monitor functions */
156
157 struct xcv_api_table {
158         const char *name;
159         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
160 };
161
162 static void prune_printername_cache(void);
163
164 /********************************************************************
165  * Canonicalize servername.
166  ********************************************************************/
167
168 static const char *canon_servername(const char *servername)
169 {
170         const char *pservername = servername;
171         while (*pservername == '\\') {
172                 pservername++;
173         }
174         return pservername;
175 }
176
177 /* translate between internal status numbers and NT status numbers */
178 static int nt_printj_status(int v)
179 {
180         switch (v) {
181         case LPQ_QUEUED:
182                 return 0;
183         case LPQ_PAUSED:
184                 return JOB_STATUS_PAUSED;
185         case LPQ_SPOOLING:
186                 return JOB_STATUS_SPOOLING;
187         case LPQ_PRINTING:
188                 return JOB_STATUS_PRINTING;
189         case LPQ_ERROR:
190                 return JOB_STATUS_ERROR;
191         case LPQ_DELETING:
192                 return JOB_STATUS_DELETING;
193         case LPQ_OFFLINE:
194                 return JOB_STATUS_OFFLINE;
195         case LPQ_PAPEROUT:
196                 return JOB_STATUS_PAPEROUT;
197         case LPQ_PRINTED:
198                 return JOB_STATUS_PRINTED;
199         case LPQ_DELETED:
200                 return JOB_STATUS_DELETED;
201         case LPQ_BLOCKED:
202                 return JOB_STATUS_BLOCKED_DEVQ;
203         case LPQ_USER_INTERVENTION:
204                 return JOB_STATUS_USER_INTERVENTION;
205         }
206         return 0;
207 }
208
209 static int nt_printq_status(int v)
210 {
211         switch (v) {
212         case LPQ_PAUSED:
213                 return PRINTER_STATUS_PAUSED;
214         case LPQ_QUEUED:
215         case LPQ_SPOOLING:
216         case LPQ_PRINTING:
217                 return 0;
218         }
219         return 0;
220 }
221
222 /***************************************************************************
223  Disconnect from the client
224 ****************************************************************************/
225
226 static void srv_spoolss_replycloseprinter(int snum,
227                                           struct printer_handle *prn_hnd)
228 {
229         WERROR result;
230         NTSTATUS status;
231
232         /*
233          * Tell the specific printing tdb we no longer want messages for this printer
234          * by deregistering our PID.
235          */
236
237         if (!print_notify_deregister_pid(snum)) {
238                 DEBUG(0, ("Failed to register our pid for printer %s\n",
239                           lp_const_servicename(snum)));
240         }
241
242         /* weird if the test succeeds !!! */
243         if (prn_hnd->notify.cli_chan == NULL ||
244             prn_hnd->notify.cli_chan->active_connections == 0) {
245                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
246                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
247                 TALLOC_FREE(prn_hnd->notify.cli_chan);
248                 return;
249         }
250
251         status = dcerpc_spoolss_ReplyClosePrinter(
252                                         prn_hnd->notify.cli_chan->binding_handle,
253                                         talloc_tos(),
254                                         &prn_hnd->notify.cli_hnd,
255                                         &result);
256         if (!NT_STATUS_IS_OK(status)) {
257                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
258                           nt_errstr(status)));
259                 result = ntstatus_to_werror(status);
260         } else if (!W_ERROR_IS_OK(result)) {
261                 DEBUG(0, ("reply_close_printer failed [%s].\n",
262                           win_errstr(result)));
263         }
264
265         /* if it's the last connection, deconnect the IPC$ share */
266         if (prn_hnd->notify.cli_chan->active_connections == 1) {
267
268                 prn_hnd->notify.cli_chan->binding_handle = NULL;
269                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
270                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
271                 TALLOC_FREE(prn_hnd->notify.cli_chan);
272
273                 if (prn_hnd->notify.msg_ctx != NULL) {
274                         messaging_deregister(prn_hnd->notify.msg_ctx,
275                                              MSG_PRINTER_NOTIFY2, NULL);
276
277                         /*
278                          * Tell the serverid.tdb we're no longer
279                          * interested in printer notify messages.
280                          */
281
282                         serverid_register_msg_flags(
283                                 messaging_server_id(prn_hnd->notify.msg_ctx),
284                                 false, FLAG_MSG_PRINT_NOTIFY);
285                 }
286         }
287
288         if (prn_hnd->notify.cli_chan) {
289                 prn_hnd->notify.cli_chan->active_connections--;
290         }
291 }
292
293 /****************************************************************************
294  Functions to free a printer entry datastruct.
295 ****************************************************************************/
296
297 static int printer_entry_destructor(struct printer_handle *Printer)
298 {
299         if (Printer->notify.cli_chan != NULL &&
300             Printer->notify.cli_chan->active_connections > 0) {
301                 int snum = -1;
302
303                 switch(Printer->printer_type) {
304                 case SPLHND_SERVER:
305                         srv_spoolss_replycloseprinter(snum, Printer);
306                         break;
307
308                 case SPLHND_PRINTER:
309                         snum = print_queue_snum(Printer->sharename);
310                         if (snum != -1) {
311                                 srv_spoolss_replycloseprinter(snum, Printer);
312                         }
313                         break;
314                 default:
315                         break;
316                 }
317         }
318
319         Printer->notify.flags=0;
320         Printer->notify.options=0;
321         Printer->notify.localmachine[0]='\0';
322         Printer->notify.printerlocal=0;
323         TALLOC_FREE(Printer->notify.option);
324         TALLOC_FREE(Printer->devmode);
325
326         /* Remove from the internal list. */
327         DLIST_REMOVE(printers_list, Printer);
328         return 0;
329 }
330
331 /****************************************************************************
332   find printer index by handle
333 ****************************************************************************/
334
335 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
336                                                         struct policy_handle *hnd)
337 {
338         struct printer_handle *find_printer = NULL;
339
340         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
341                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
342                 return NULL;
343         }
344
345         return find_printer;
346 }
347
348 /****************************************************************************
349  Close printer index by handle.
350 ****************************************************************************/
351
352 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
353 {
354         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
355
356         if (!Printer) {
357                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
358                         OUR_HANDLE(hnd)));
359                 return false;
360         }
361
362         close_policy_hnd(p, hnd);
363
364         return true;
365 }
366
367 /****************************************************************************
368  Delete a printer given a handle.
369 ****************************************************************************/
370
371 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
372                                   const char *sharename,
373                                   struct messaging_context *msg_ctx)
374 {
375         char *cmd = lp_deleteprinter_cmd();
376         char *command = NULL;
377         int ret;
378         bool is_print_op = false;
379
380         /* can't fail if we don't try */
381
382         if ( !*cmd )
383                 return WERR_OK;
384
385         command = talloc_asprintf(ctx,
386                         "%s \"%s\"",
387                         cmd, sharename);
388         if (!command) {
389                 return WERR_NOMEM;
390         }
391         if ( token )
392                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
393
394         DEBUG(10,("Running [%s]\n", command));
395
396         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
397
398         if ( is_print_op )
399                 become_root();
400
401         if ( (ret = smbrun(command, NULL)) == 0 ) {
402                 /* Tell everyone we updated smb.conf. */
403                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
404         }
405
406         if ( is_print_op )
407                 unbecome_root();
408
409         /********** END SePrintOperatorPrivlege BLOCK **********/
410
411         DEBUGADD(10,("returned [%d]\n", ret));
412
413         TALLOC_FREE(command);
414
415         if (ret != 0)
416                 return WERR_BADFID; /* What to return here? */
417
418         /* go ahead and re-read the services immediately */
419         become_root();
420         reload_services(msg_ctx, -1, false);
421         unbecome_root();
422
423         if ( lp_servicenumber( sharename ) >= 0 )
424                 return WERR_ACCESS_DENIED;
425
426         return WERR_OK;
427 }
428
429 /****************************************************************************
430  Delete a printer given a handle.
431 ****************************************************************************/
432
433 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
434 {
435         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
436         WERROR result;
437
438         if (!Printer) {
439                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
440                         OUR_HANDLE(hnd)));
441                 return WERR_BADFID;
442         }
443
444         /*
445          * It turns out that Windows allows delete printer on a handle
446          * opened by an admin user, then used on a pipe handle created
447          * by an anonymous user..... but they're working on security.... riiight !
448          * JRA.
449          */
450
451         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
452                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
453                 return WERR_ACCESS_DENIED;
454         }
455
456         /* this does not need a become root since the access check has been
457            done on the handle already */
458
459         result = winreg_delete_printer_key(p->mem_ctx,
460                                            get_session_info_system(),
461                                            p->msg_ctx,
462                                            Printer->sharename,
463                                            "");
464         if (!W_ERROR_IS_OK(result)) {
465                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
466                 return WERR_BADFID;
467         }
468
469         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
470                                      Printer->sharename, p->msg_ctx);
471         if (!W_ERROR_IS_OK(result)) {
472                 return result;
473         }
474         prune_printername_cache();
475         return WERR_OK;
476 }
477
478 /****************************************************************************
479  Return the snum of a printer corresponding to an handle.
480 ****************************************************************************/
481
482 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
483                              int *number, struct share_params **params)
484 {
485         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
486
487         if (!Printer) {
488                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
489                         OUR_HANDLE(hnd)));
490                 return false;
491         }
492
493         switch (Printer->printer_type) {
494                 case SPLHND_PRINTER:
495                         DEBUG(4,("short name:%s\n", Printer->sharename));
496                         *number = print_queue_snum(Printer->sharename);
497                         return (*number != -1);
498                 case SPLHND_SERVER:
499                         return false;
500                 default:
501                         return false;
502         }
503 }
504
505 /****************************************************************************
506  Set printer handle type.
507  Check if it's \\server or \\server\printer
508 ****************************************************************************/
509
510 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
511 {
512         DEBUG(3,("Setting printer type=%s\n", handlename));
513
514         /* it's a print server */
515         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
516                 DEBUGADD(4,("Printer is a print server\n"));
517                 Printer->printer_type = SPLHND_SERVER;
518         }
519         /* it's a printer (set_printer_hnd_name() will handle port monitors */
520         else {
521                 DEBUGADD(4,("Printer is a printer\n"));
522                 Printer->printer_type = SPLHND_PRINTER;
523         }
524
525         return true;
526 }
527
528 static void prune_printername_cache_fn(const char *key, const char *value,
529                                        time_t timeout, void *private_data)
530 {
531         gencache_del(key);
532 }
533
534 static void prune_printername_cache(void)
535 {
536         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
537 }
538
539 /****************************************************************************
540  Set printer handle name..  Accept names like \\server, \\server\printer,
541  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
542  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
543  XcvDataPort() interface.
544 ****************************************************************************/
545
546 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
547                                    const struct auth_serversupplied_info *session_info,
548                                    struct messaging_context *msg_ctx,
549                                    struct printer_handle *Printer,
550                                    const char *handlename)
551 {
552         int snum;
553         int n_services=lp_numservices();
554         char *aprinter;
555         const char *printername;
556         const char *servername = NULL;
557         fstring sname;
558         bool found = false;
559         struct spoolss_PrinterInfo2 *info2 = NULL;
560         WERROR result;
561         char *p;
562
563         /*
564          * Hopefully nobody names his printers like this. Maybe \ or ,
565          * are illegal in printer names even?
566          */
567         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
568         char *cache_key;
569         char *tmp;
570
571         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
572                 (unsigned long)strlen(handlename)));
573
574         aprinter = CONST_DISCARD(char *, handlename);
575         if ( *handlename == '\\' ) {
576                 servername = canon_servername(handlename);
577                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
578                         *aprinter = '\0';
579                         aprinter++;
580                 }
581                 if (!is_myname_or_ipaddr(servername)) {
582                         return WERR_INVALID_PRINTER_NAME;
583                 }
584                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
585                 if (Printer->servername == NULL) {
586                         return WERR_NOMEM;
587                 }
588         }
589
590         if (Printer->printer_type == SPLHND_SERVER) {
591                 return WERR_OK;
592         }
593
594         if (Printer->printer_type != SPLHND_PRINTER) {
595                 return WERR_INVALID_HANDLE;
596         }
597
598         DEBUGADD(5, ("searching for [%s]\n", aprinter));
599
600         p = strchr(aprinter, ',');
601         if (p != NULL) {
602                 char *p2 = p;
603                 p++;
604                 if (*p == ' ') {
605                         p++;
606                 }
607                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
608                         *p2 = '\0';
609                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
610                         *p2 = '\0';
611                 }
612         }
613
614         if (p) {
615                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
616         }
617
618         /* check for the Port Monitor Interface */
619         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
620                 Printer->printer_type = SPLHND_PORTMON_TCP;
621                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
622                 found = true;
623         }
624         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
625                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
626                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
627                 found = true;
628         }
629
630         /*
631          * With hundreds of printers, the "for" loop iterating all
632          * shares can be quite expensive, as it is done on every
633          * OpenPrinter. The loop maps "aprinter" to "sname", the
634          * result of which we cache in gencache.
635          */
636
637         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
638                                     aprinter);
639         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
640
641                 found = (strcmp(tmp, printer_not_found) != 0);
642                 if (!found) {
643                         DEBUG(4, ("Printer %s not found\n", aprinter));
644                         SAFE_FREE(tmp);
645                         return WERR_INVALID_PRINTER_NAME;
646                 }
647                 fstrcpy(sname, tmp);
648                 SAFE_FREE(tmp);
649         }
650
651         /* Search all sharenames first as this is easier than pulling
652            the printer_info_2 off of disk. Don't use find_service() since
653            that calls out to map_username() */
654
655         /* do another loop to look for printernames */
656         for (snum = 0; !found && snum < n_services; snum++) {
657                 const char *printer = lp_const_servicename(snum);
658
659                 /* no point going on if this is not a printer */
660                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
661                         continue;
662                 }
663
664                 /* ignore [printers] share */
665                 if (strequal(printer, "printers")) {
666                         continue;
667                 }
668
669                 fstrcpy(sname, printer);
670                 if (strequal(aprinter, printer)) {
671                         found = true;
672                         break;
673                 }
674
675                 /* no point looking up the printer object if
676                    we aren't allowing printername != sharename */
677                 if (lp_force_printername(snum)) {
678                         continue;
679                 }
680
681                 result = winreg_get_printer(mem_ctx,
682                                             session_info,
683                                             msg_ctx,
684                                             sname,
685                                             &info2);
686                 if ( !W_ERROR_IS_OK(result) ) {
687                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
688                                  sname, win_errstr(result)));
689                         continue;
690                 }
691
692                 printername = strrchr(info2->printername, '\\');
693                 if (printername == NULL) {
694                         printername = info2->printername;
695                 } else {
696                         printername++;
697                 }
698
699                 if (strequal(printername, aprinter)) {
700                         found = true;
701                         break;
702                 }
703
704                 DEBUGADD(10, ("printername: %s\n", printername));
705
706                 TALLOC_FREE(info2);
707         }
708
709         if ( !found ) {
710                 if (cache_key != NULL) {
711                         gencache_set(cache_key, printer_not_found,
712                                      time(NULL)+300);
713                         TALLOC_FREE(cache_key);
714                 }
715                 DEBUGADD(4,("Printer not found\n"));
716                 return WERR_INVALID_PRINTER_NAME;
717         }
718
719         if (cache_key != NULL) {
720                 gencache_set(cache_key, sname, time(NULL)+300);
721                 TALLOC_FREE(cache_key);
722         }
723
724         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
725
726         fstrcpy(Printer->sharename, sname);
727
728         return WERR_OK;
729 }
730
731 /****************************************************************************
732  Find first available printer slot. creates a printer handle for you.
733  ****************************************************************************/
734
735 static WERROR open_printer_hnd(struct pipes_struct *p,
736                                struct policy_handle *hnd,
737                                const char *name,
738                                uint32_t access_granted)
739 {
740         struct printer_handle *new_printer;
741         WERROR result;
742
743         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
744
745         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
746         if (new_printer == NULL) {
747                 return WERR_NOMEM;
748         }
749         talloc_set_destructor(new_printer, printer_entry_destructor);
750
751         /* This also steals the printer_handle on the policy_handle */
752         if (!create_policy_hnd(p, hnd, new_printer)) {
753                 TALLOC_FREE(new_printer);
754                 return WERR_INVALID_HANDLE;
755         }
756
757         /* Add to the internal list. */
758         DLIST_ADD(printers_list, new_printer);
759
760         new_printer->notify.option=NULL;
761
762         if (!set_printer_hnd_printertype(new_printer, name)) {
763                 close_printer_handle(p, hnd);
764                 return WERR_INVALID_HANDLE;
765         }
766
767         result = set_printer_hnd_name(p->mem_ctx,
768                                       get_session_info_system(),
769                                       p->msg_ctx,
770                                       new_printer, name);
771         if (!W_ERROR_IS_OK(result)) {
772                 close_printer_handle(p, hnd);
773                 return result;
774         }
775
776         new_printer->access_granted = access_granted;
777
778         DEBUG(5, ("%d printer handles active\n",
779                   (int)num_pipe_handles(p)));
780
781         return WERR_OK;
782 }
783
784 /***************************************************************************
785  check to see if the client motify handle is monitoring the notification
786  given by (notify_type, notify_field).
787  **************************************************************************/
788
789 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
790                                       uint16_t notify_field)
791 {
792         return true;
793 }
794
795 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
796                                 uint16_t notify_field)
797 {
798         struct spoolss_NotifyOption *option = p->notify.option;
799         uint32_t i, j;
800
801         /*
802          * Flags should always be zero when the change notify
803          * is registered by the client's spooler.  A user Win32 app
804          * might use the flags though instead of the NOTIFY_OPTION_INFO
805          * --jerry
806          */
807
808         if (!option) {
809                 return false;
810         }
811
812         if (p->notify.flags)
813                 return is_monitoring_event_flags(
814                         p->notify.flags, notify_type, notify_field);
815
816         for (i = 0; i < option->count; i++) {
817
818                 /* Check match for notify_type */
819
820                 if (option->types[i].type != notify_type)
821                         continue;
822
823                 /* Check match for field */
824
825                 for (j = 0; j < option->types[i].count; j++) {
826                         if (option->types[i].fields[j].field == notify_field) {
827                                 return true;
828                         }
829                 }
830         }
831
832         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
833                    p->servername, p->sharename, notify_type, notify_field));
834
835         return false;
836 }
837
838 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
839         _data->data.integer[0] = _integer; \
840         _data->data.integer[1] = 0;
841
842
843 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
844         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
845         if (!_data->data.string.string) {\
846                 _data->data.string.size = 0; \
847         } \
848         _data->data.string.size = strlen_m_term(_p) * 2;
849
850 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
851         _data->data.devmode.devmode = _devmode;
852
853 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
854         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
855         if (!_data->data.sd.sd) { \
856                 _data->data.sd.sd_size = 0; \
857         } \
858         _data->data.sd.sd_size = \
859                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
860
861 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
862                                    struct tm *t,
863                                    const char **pp,
864                                    uint32_t *plen)
865 {
866         struct spoolss_Time st;
867         uint32_t len = 16;
868         char *p;
869
870         if (!init_systemtime(&st, t)) {
871                 return;
872         }
873
874         p = talloc_array(mem_ctx, char, len);
875         if (!p) {
876                 return;
877         }
878
879         /*
880          * Systemtime must be linearized as a set of UINT16's.
881          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
882          */
883
884         SSVAL(p, 0, st.year);
885         SSVAL(p, 2, st.month);
886         SSVAL(p, 4, st.day_of_week);
887         SSVAL(p, 6, st.day);
888         SSVAL(p, 8, st.hour);
889         SSVAL(p, 10, st.minute);
890         SSVAL(p, 12, st.second);
891         SSVAL(p, 14, st.millisecond);
892
893         *pp = p;
894         *plen = len;
895 }
896
897 /* Convert a notification message to a struct spoolss_Notify */
898
899 static void notify_one_value(struct spoolss_notify_msg *msg,
900                              struct spoolss_Notify *data,
901                              TALLOC_CTX *mem_ctx)
902 {
903         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
904 }
905
906 static void notify_string(struct spoolss_notify_msg *msg,
907                           struct spoolss_Notify *data,
908                           TALLOC_CTX *mem_ctx)
909 {
910         /* The length of the message includes the trailing \0 */
911
912         data->data.string.size = msg->len * 2;
913         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
914         if (!data->data.string.string) {
915                 data->data.string.size = 0;
916                 return;
917         }
918 }
919
920 static void notify_system_time(struct spoolss_notify_msg *msg,
921                                struct spoolss_Notify *data,
922                                TALLOC_CTX *mem_ctx)
923 {
924         data->data.string.string = NULL;
925         data->data.string.size = 0;
926
927         if (msg->len != sizeof(time_t)) {
928                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
929                           msg->len));
930                 return;
931         }
932
933         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
934                                &data->data.string.string,
935                                &data->data.string.size);
936 }
937
938 struct notify2_message_table {
939         const char *name;
940         void (*fn)(struct spoolss_notify_msg *msg,
941                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
942 };
943
944 static struct notify2_message_table printer_notify_table[] = {
945         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
946         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
947         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
948         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
949         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
950         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
951         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
952         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
953         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
954         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
955         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
956         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
957         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
958         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
959         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
960         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
961         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
962         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
963         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
964 };
965
966 static struct notify2_message_table job_notify_table[] = {
967         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
968         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
969         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
970         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
971         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
972         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
973         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
974         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
975         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
976         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
977         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
978         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
979         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
980         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
981         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
982         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
983         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
984         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
985         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
986         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
987         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
988         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
989         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
990         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
991 };
992
993
994 /***********************************************************************
995  Allocate talloc context for container object
996  **********************************************************************/
997
998 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
999 {
1000         if ( !ctr )
1001                 return;
1002
1003         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1004
1005         return;
1006 }
1007
1008 /***********************************************************************
1009  release all allocated memory and zero out structure
1010  **********************************************************************/
1011
1012 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1013 {
1014         if ( !ctr )
1015                 return;
1016
1017         if ( ctr->ctx )
1018                 talloc_destroy(ctr->ctx);
1019
1020         ZERO_STRUCTP(ctr);
1021
1022         return;
1023 }
1024
1025 /***********************************************************************
1026  **********************************************************************/
1027
1028 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1029 {
1030         if ( !ctr )
1031                 return NULL;
1032
1033         return ctr->ctx;
1034 }
1035
1036 /***********************************************************************
1037  **********************************************************************/
1038
1039 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1040 {
1041         if ( !ctr || !ctr->msg_groups )
1042                 return NULL;
1043
1044         if ( idx >= ctr->num_groups )
1045                 return NULL;
1046
1047         return &ctr->msg_groups[idx];
1048
1049 }
1050
1051 /***********************************************************************
1052  How many groups of change messages do we have ?
1053  **********************************************************************/
1054
1055 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1056 {
1057         if ( !ctr )
1058                 return 0;
1059
1060         return ctr->num_groups;
1061 }
1062
1063 /***********************************************************************
1064  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1065  **********************************************************************/
1066
1067 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1068 {
1069         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1070         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1071         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1072         int                             i, new_slot;
1073
1074         if ( !ctr || !msg )
1075                 return 0;
1076
1077         /* loop over all groups looking for a matching printer name */
1078
1079         for ( i=0; i<ctr->num_groups; i++ ) {
1080                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1081                         break;
1082         }
1083
1084         /* add a new group? */
1085
1086         if ( i == ctr->num_groups ) {
1087                 ctr->num_groups++;
1088
1089                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1090                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1091                         return 0;
1092                 }
1093                 ctr->msg_groups = groups;
1094
1095                 /* clear the new entry and set the printer name */
1096
1097                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1098                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1099         }
1100
1101         /* add the change messages; 'i' is the correct index now regardless */
1102
1103         msg_grp = &ctr->msg_groups[i];
1104
1105         msg_grp->num_msgs++;
1106
1107         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1108                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1109                 return 0;
1110         }
1111         msg_grp->msgs = msg_list;
1112
1113         new_slot = msg_grp->num_msgs-1;
1114         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1115
1116         /* need to allocate own copy of data */
1117
1118         if ( msg->len != 0 )
1119                 msg_grp->msgs[new_slot].notify.data = (char *)
1120                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1121
1122         return ctr->num_groups;
1123 }
1124
1125 static void construct_info_data(struct spoolss_Notify *info_data,
1126                                 enum spoolss_NotifyType type,
1127                                 uint16_t field, int id);
1128
1129 /***********************************************************************
1130  Send a change notication message on all handles which have a call
1131  back registered
1132  **********************************************************************/
1133
1134 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1135                                   struct printer_handle *prn_hnd,
1136                                   SPOOLSS_NOTIFY_MSG *messages,
1137                                   uint32_t num_msgs,
1138                                   struct spoolss_Notify **_notifies,
1139                                   int *_count)
1140 {
1141         struct spoolss_Notify *notifies;
1142         SPOOLSS_NOTIFY_MSG *msg;
1143         int count = 0;
1144         uint32_t id;
1145         int i;
1146
1147         notifies = talloc_zero_array(mem_ctx,
1148                                      struct spoolss_Notify, num_msgs);
1149         if (!notifies) {
1150                 return ENOMEM;
1151         }
1152
1153         for (i = 0; i < num_msgs; i++) {
1154
1155                 msg = &messages[i];
1156
1157                 /* Are we monitoring this event? */
1158
1159                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1160                         continue;
1161                 }
1162
1163                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1164                            "for printer [%s]\n",
1165                            msg->type, msg->field, prn_hnd->sharename));
1166
1167                 /*
1168                  * if the is a printer notification handle and not a job
1169                  * notification type, then set the id to 0.
1170                  * Otherwise just use what was specified in the message.
1171                  *
1172                  * When registering change notification on a print server
1173                  * handle we always need to send back the id (snum) matching
1174                  * the printer for which the change took place.
1175                  * For change notify registered on a printer handle,
1176                  * this does not matter and the id should be 0.
1177                  *
1178                  * --jerry
1179                  */
1180
1181                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1182                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1183                         id = 0;
1184                 } else {
1185                         id = msg->id;
1186                 }
1187
1188                 /* Convert unix jobid to smb jobid */
1189
1190                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1191                         id = sysjob_to_jobid(msg->id);
1192
1193                         if (id == -1) {
1194                                 DEBUG(3, ("no such unix jobid %d\n",
1195                                           msg->id));
1196                                 continue;
1197                         }
1198                 }
1199
1200                 construct_info_data(&notifies[count],
1201                                     msg->type, msg->field, id);
1202
1203                 switch(msg->type) {
1204                 case PRINTER_NOTIFY_TYPE:
1205                         if (printer_notify_table[msg->field].fn) {
1206                                 printer_notify_table[msg->field].fn(msg,
1207                                                 &notifies[count], mem_ctx);
1208                         }
1209                         break;
1210
1211                 case JOB_NOTIFY_TYPE:
1212                         if (job_notify_table[msg->field].fn) {
1213                                 job_notify_table[msg->field].fn(msg,
1214                                                 &notifies[count], mem_ctx);
1215                         }
1216                         break;
1217
1218                 default:
1219                         DEBUG(5, ("Unknown notification type %d\n",
1220                                   msg->type));
1221                         continue;
1222                 }
1223
1224                 count++;
1225         }
1226
1227         *_notifies = notifies;
1228         *_count = count;
1229
1230         return 0;
1231 }
1232
1233 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1234                                 struct printer_handle *prn_hnd,
1235                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1236 {
1237         struct spoolss_Notify *notifies;
1238         int count = 0;
1239         union spoolss_ReplyPrinterInfo info;
1240         struct spoolss_NotifyInfo info0;
1241         uint32_t reply_result;
1242         NTSTATUS status;
1243         WERROR werr;
1244         int ret;
1245
1246         /* Is there notification on this handle? */
1247         if (prn_hnd->notify.cli_chan == NULL ||
1248             prn_hnd->notify.cli_chan->active_connections == 0) {
1249                 return 0;
1250         }
1251
1252         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1253                    prn_hnd->servername, prn_hnd->sharename));
1254
1255         /* For this printer? Print servers always receive notifications. */
1256         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1257             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1258                 return 0;
1259         }
1260
1261         DEBUG(10,("Our printer\n"));
1262
1263         /* build the array of change notifications */
1264         ret = build_notify2_messages(mem_ctx, prn_hnd,
1265                                      msg_group->msgs,
1266                                      msg_group->num_msgs,
1267                                      &notifies, &count);
1268         if (ret) {
1269                 return ret;
1270         }
1271
1272         info0.version   = 0x2;
1273         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1274         info0.count     = count;
1275         info0.notifies  = notifies;
1276
1277         info.info0 = &info0;
1278
1279         status = dcerpc_spoolss_RouterReplyPrinterEx(
1280                                 prn_hnd->notify.cli_chan->binding_handle,
1281                                 mem_ctx,
1282                                 &prn_hnd->notify.cli_hnd,
1283                                 prn_hnd->notify.change, /* color */
1284                                 prn_hnd->notify.flags,
1285                                 &reply_result,
1286                                 0, /* reply_type, must be 0 */
1287                                 info, &werr);
1288         if (!NT_STATUS_IS_OK(status)) {
1289                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1290                           "failed: %s\n",
1291                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1292                           nt_errstr(status)));
1293                 werr = ntstatus_to_werror(status);
1294         } else if (!W_ERROR_IS_OK(werr)) {
1295                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1296                           "failed: %s\n",
1297                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1298                           win_errstr(werr)));
1299         }
1300         switch (reply_result) {
1301         case 0:
1302                 break;
1303         case PRINTER_NOTIFY_INFO_DISCARDED:
1304         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1305         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1306                 break;
1307         default:
1308                 break;
1309         }
1310
1311         return 0;
1312 }
1313
1314 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1315 {
1316         struct printer_handle    *p;
1317         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1318         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1319         int ret;
1320
1321         if ( !msg_group ) {
1322                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1323                 return;
1324         }
1325
1326         if (!msg_group->msgs) {
1327                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1328                 return;
1329         }
1330
1331         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1332
1333         /* loop over all printers */
1334
1335         for (p = printers_list; p; p = p->next) {
1336                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1337                 if (ret) {
1338                         goto done;
1339                 }
1340         }
1341
1342 done:
1343         DEBUG(8,("send_notify2_changes: Exit...\n"));
1344         return;
1345 }
1346
1347 /***********************************************************************
1348  **********************************************************************/
1349
1350 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1351 {
1352
1353         uint32_t tv_sec, tv_usec;
1354         size_t offset = 0;
1355
1356         /* Unpack message */
1357
1358         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1359                              msg->printer);
1360
1361         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1362                                 &tv_sec, &tv_usec,
1363                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1364
1365         if (msg->len == 0)
1366                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1367                            &msg->notify.value[0], &msg->notify.value[1]);
1368         else
1369                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1370                            &msg->len, &msg->notify.data);
1371
1372         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1373                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1374
1375         tv->tv_sec = tv_sec;
1376         tv->tv_usec = tv_usec;
1377
1378         if (msg->len == 0)
1379                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1380                           msg->notify.value[1]));
1381         else
1382                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1383
1384         return true;
1385 }
1386
1387 /********************************************************************
1388  Receive a notify2 message list
1389  ********************************************************************/
1390
1391 static void receive_notify2_message_list(struct messaging_context *msg,
1392                                          void *private_data,
1393                                          uint32_t msg_type,
1394                                          struct server_id server_id,
1395                                          DATA_BLOB *data)
1396 {
1397         size_t                  msg_count, i;
1398         char                    *buf = (char *)data->data;
1399         char                    *msg_ptr;
1400         size_t                  msg_len;
1401         SPOOLSS_NOTIFY_MSG      notify;
1402         SPOOLSS_NOTIFY_MSG_CTR  messages;
1403         int                     num_groups;
1404
1405         if (data->length < 4) {
1406                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1407                 return;
1408         }
1409
1410         msg_count = IVAL(buf, 0);
1411         msg_ptr = buf + 4;
1412
1413         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1414
1415         if (msg_count == 0) {
1416                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1417                 return;
1418         }
1419
1420         /* initialize the container */
1421
1422         ZERO_STRUCT( messages );
1423         notify_msg_ctr_init( &messages );
1424
1425         /*
1426          * build message groups for each printer identified
1427          * in a change_notify msg.  Remember that a PCN message
1428          * includes the handle returned for the srv_spoolss_replyopenprinter()
1429          * call.  Therefore messages are grouped according to printer handle.
1430          */
1431
1432         for ( i=0; i<msg_count; i++ ) {
1433                 struct timeval msg_tv;
1434
1435                 if (msg_ptr + 4 - buf > data->length) {
1436                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1437                         return;
1438                 }
1439
1440                 msg_len = IVAL(msg_ptr,0);
1441                 msg_ptr += 4;
1442
1443                 if (msg_ptr + msg_len - buf > data->length) {
1444                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1445                         return;
1446                 }
1447
1448                 /* unpack messages */
1449
1450                 ZERO_STRUCT( notify );
1451                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1452                 msg_ptr += msg_len;
1453
1454                 /* add to correct list in container */
1455
1456                 notify_msg_ctr_addmsg( &messages, &notify );
1457
1458                 /* free memory that might have been allocated by notify2_unpack_msg() */
1459
1460                 if ( notify.len != 0 )
1461                         SAFE_FREE( notify.notify.data );
1462         }
1463
1464         /* process each group of messages */
1465
1466         num_groups = notify_msg_ctr_numgroups( &messages );
1467         for ( i=0; i<num_groups; i++ )
1468                 send_notify2_changes( &messages, i );
1469
1470
1471         /* cleanup */
1472
1473         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1474                 (uint32_t)msg_count ));
1475
1476         notify_msg_ctr_destroy( &messages );
1477
1478         return;
1479 }
1480
1481 /********************************************************************
1482  Send a message to ourself about new driver being installed
1483  so we can upgrade the information for each printer bound to this
1484  driver
1485  ********************************************************************/
1486
1487 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1488                                             struct messaging_context *msg_ctx)
1489 {
1490         int len = strlen(drivername);
1491
1492         if (!len)
1493                 return false;
1494
1495         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1496                 drivername));
1497
1498         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1499                            MSG_PRINTER_DRVUPGRADE,
1500                            (uint8_t *)drivername, len+1);
1501
1502         return true;
1503 }
1504
1505 void srv_spoolss_cleanup(void)
1506 {
1507         struct printer_session_counter *session_counter;
1508
1509         for (session_counter = counter_list;
1510              session_counter != NULL;
1511              session_counter = counter_list) {
1512                 DLIST_REMOVE(counter_list, session_counter);
1513                 TALLOC_FREE(session_counter);
1514         }
1515 }
1516
1517 /**********************************************************************
1518  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1519  over all printers, upgrading ones as necessary
1520  **********************************************************************/
1521
1522 void do_drv_upgrade_printer(struct messaging_context *msg,
1523                             void *private_data,
1524                             uint32_t msg_type,
1525                             struct server_id server_id,
1526                             DATA_BLOB *data)
1527 {
1528         TALLOC_CTX *tmp_ctx;
1529         struct auth_serversupplied_info *session_info = NULL;
1530         struct spoolss_PrinterInfo2 *pinfo2;
1531         NTSTATUS status;
1532         WERROR result;
1533         const char *drivername;
1534         int snum;
1535         int n_services = lp_numservices();
1536
1537         tmp_ctx = talloc_new(NULL);
1538         if (!tmp_ctx) return;
1539
1540         status = make_session_info_system(tmp_ctx, &session_info);
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 DEBUG(0, ("do_drv_upgrade_printer: "
1543                           "Could not create system session_info\n"));
1544                 goto done;
1545         }
1546
1547         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1548         if (!drivername) {
1549                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1550                 goto done;
1551         }
1552
1553         DEBUG(10, ("do_drv_upgrade_printer: "
1554                    "Got message for new driver [%s]\n", drivername));
1555
1556         /* Iterate the printer list */
1557
1558         for (snum = 0; snum < n_services; snum++) {
1559                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1560                         continue;
1561                 }
1562
1563                 /* ignore [printers] share */
1564                 if (strequal(lp_const_servicename(snum), "printers")) {
1565                         continue;
1566                 }
1567
1568                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1569                                             lp_const_servicename(snum),
1570                                             &pinfo2);
1571
1572                 if (!W_ERROR_IS_OK(result)) {
1573                         continue;
1574                 }
1575
1576                 if (!pinfo2->drivername) {
1577                         continue;
1578                 }
1579
1580                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1581                         continue;
1582                 }
1583
1584                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1585
1586                 /* all we care about currently is the change_id */
1587                 result = winreg_printer_update_changeid(tmp_ctx,
1588                                                         session_info,
1589                                                         msg,
1590                                                         pinfo2->printername);
1591
1592                 if (!W_ERROR_IS_OK(result)) {
1593                         DEBUG(3, ("do_drv_upgrade_printer: "
1594                                   "Failed to update changeid [%s]\n",
1595                                   win_errstr(result)));
1596                 }
1597         }
1598
1599         /* all done */
1600 done:
1601         talloc_free(tmp_ctx);
1602 }
1603
1604 /********************************************************************
1605  Update the cache for all printq's with a registered client
1606  connection
1607  ********************************************************************/
1608
1609 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1610 {
1611         struct printer_handle *printer = printers_list;
1612         int snum;
1613
1614         /* loop through all printers and update the cache where
1615            a client is connected */
1616         while (printer) {
1617                 if ((printer->printer_type == SPLHND_PRINTER) &&
1618                     ((printer->notify.cli_chan != NULL) &&
1619                      (printer->notify.cli_chan->active_connections > 0))) {
1620                         snum = print_queue_snum(printer->sharename);
1621                         print_queue_status(msg_ctx, snum, NULL, NULL);
1622                 }
1623
1624                 printer = printer->next;
1625         }
1626
1627         return;
1628 }
1629
1630 /****************************************************************
1631  _spoolss_OpenPrinter
1632 ****************************************************************/
1633
1634 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1635                             struct spoolss_OpenPrinter *r)
1636 {
1637         struct spoolss_OpenPrinterEx e;
1638         WERROR werr;
1639
1640         ZERO_STRUCT(e.in.userlevel);
1641
1642         e.in.printername        = r->in.printername;
1643         e.in.datatype           = r->in.datatype;
1644         e.in.devmode_ctr        = r->in.devmode_ctr;
1645         e.in.access_mask        = r->in.access_mask;
1646         e.in.level              = 0;
1647
1648         e.out.handle            = r->out.handle;
1649
1650         werr = _spoolss_OpenPrinterEx(p, &e);
1651
1652         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1653                 /* OpenPrinterEx returns this for a bad
1654                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1655                  * instead.
1656                  */
1657                 werr = WERR_INVALID_PRINTER_NAME;
1658         }
1659
1660         return werr;
1661 }
1662
1663 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1664                               struct spoolss_DeviceMode *orig,
1665                               struct spoolss_DeviceMode **dest)
1666 {
1667         struct spoolss_DeviceMode *dm;
1668
1669         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1670         if (!dm) {
1671                 return WERR_NOMEM;
1672         }
1673
1674         /* copy all values, then duplicate strings and structs */
1675         *dm = *orig;
1676
1677         dm->devicename = talloc_strdup(dm, orig->devicename);
1678         if (!dm->devicename) {
1679                 return WERR_NOMEM;
1680         }
1681         dm->formname = talloc_strdup(dm, orig->formname);
1682         if (!dm->formname) {
1683                 return WERR_NOMEM;
1684         }
1685         if (orig->driverextra_data.data) {
1686                 dm->driverextra_data.data =
1687                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1688                                         orig->driverextra_data.length);
1689                 if (!dm->driverextra_data.data) {
1690                         return WERR_NOMEM;
1691                 }
1692         }
1693
1694         *dest = dm;
1695         return WERR_OK;
1696 }
1697
1698 /****************************************************************
1699  _spoolss_OpenPrinterEx
1700 ****************************************************************/
1701
1702 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1703                               struct spoolss_OpenPrinterEx *r)
1704 {
1705         int snum;
1706         struct printer_handle *Printer=NULL;
1707         WERROR result;
1708
1709         if (!r->in.printername) {
1710                 return WERR_INVALID_PARAM;
1711         }
1712
1713         if (r->in.level > 3) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1717             (r->in.level == 2 && !r->in.userlevel.level2) ||
1718             (r->in.level == 3 && !r->in.userlevel.level3)) {
1719                 return WERR_INVALID_PARAM;
1720         }
1721
1722         /* some sanity check because you can open a printer or a print server */
1723         /* aka: \\server\printer or \\server */
1724
1725         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1726
1727         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1728         if (!W_ERROR_IS_OK(result)) {
1729                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1730                         "for printer %s\n", r->in.printername));
1731                 ZERO_STRUCTP(r->out.handle);
1732                 return result;
1733         }
1734
1735         Printer = find_printer_index_by_hnd(p, r->out.handle);
1736         if ( !Printer ) {
1737                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1738                         "handle we created for printer %s\n", r->in.printername));
1739                 close_printer_handle(p, r->out.handle);
1740                 ZERO_STRUCTP(r->out.handle);
1741                 return WERR_INVALID_PARAM;
1742         }
1743
1744         /*
1745          * First case: the user is opening the print server:
1746          *
1747          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1748          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1749          *
1750          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1751          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1752          * or if the user is listed in the smb.conf printer admin parameter.
1753          *
1754          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1755          * client view printer folder, but does not show the MSAPW.
1756          *
1757          * Note: this test needs code to check access rights here too. Jeremy
1758          * could you look at this?
1759          *
1760          * Second case: the user is opening a printer:
1761          * NT doesn't let us connect to a printer if the connecting user
1762          * doesn't have print permission.
1763          *
1764          * Third case: user is opening a Port Monitor
1765          * access checks same as opening a handle to the print server.
1766          */
1767
1768         switch (Printer->printer_type )
1769         {
1770         case SPLHND_SERVER:
1771         case SPLHND_PORTMON_TCP:
1772         case SPLHND_PORTMON_LOCAL:
1773                 /* Printserver handles use global struct... */
1774
1775                 snum = -1;
1776
1777                 /* Map standard access rights to object specific access rights */
1778
1779                 se_map_standard(&r->in.access_mask,
1780                                 &printserver_std_mapping);
1781
1782                 /* Deny any object specific bits that don't apply to print
1783                    servers (i.e printer and job specific bits) */
1784
1785                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1786
1787                 if (r->in.access_mask &
1788                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1789                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1790                         close_printer_handle(p, r->out.handle);
1791                         ZERO_STRUCTP(r->out.handle);
1792                         return WERR_ACCESS_DENIED;
1793                 }
1794
1795                 /* Allow admin access */
1796
1797                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1798                 {
1799                         if (!lp_ms_add_printer_wizard()) {
1800                                 close_printer_handle(p, r->out.handle);
1801                                 ZERO_STRUCTP(r->out.handle);
1802                                 return WERR_ACCESS_DENIED;
1803                         }
1804
1805                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1806                            and not a printer admin, then fail */
1807
1808                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1809                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1810                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1811                             !token_contains_name_in_list(
1812                                     uidtoname(p->session_info->utok.uid),
1813                                     p->session_info->info3->base.domain.string,
1814                                     NULL,
1815                                     p->session_info->security_token,
1816                                     lp_printer_admin(snum))) {
1817                                 close_printer_handle(p, r->out.handle);
1818                                 ZERO_STRUCTP(r->out.handle);
1819                                 DEBUG(3,("access DENIED as user is not root, "
1820                                         "has no printoperator privilege, "
1821                                         "not a member of the printoperator builtin group and "
1822                                         "is not in printer admin list"));
1823                                 return WERR_ACCESS_DENIED;
1824                         }
1825
1826                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1827                 }
1828                 else
1829                 {
1830                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1831                 }
1832
1833                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1834                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1835
1836                 /* We fall through to return WERR_OK */
1837                 break;
1838
1839         case SPLHND_PRINTER:
1840                 /* NT doesn't let us connect to a printer if the connecting user
1841                    doesn't have print permission.  */
1842
1843                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1844                         close_printer_handle(p, r->out.handle);
1845                         ZERO_STRUCTP(r->out.handle);
1846                         return WERR_BADFID;
1847                 }
1848
1849                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1850                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1851                 }
1852
1853                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1854
1855                 /* map an empty access mask to the minimum access mask */
1856                 if (r->in.access_mask == 0x0)
1857                         r->in.access_mask = PRINTER_ACCESS_USE;
1858
1859                 /*
1860                  * If we are not serving the printer driver for this printer,
1861                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1862                  * will keep NT clients happy  --jerry
1863                  */
1864
1865                 if (lp_use_client_driver(snum)
1866                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1867                 {
1868                         r->in.access_mask = PRINTER_ACCESS_USE;
1869                 }
1870
1871                 /* check smb.conf parameters and the the sec_desc */
1872
1873                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1874                                   p->client_id->name, p->client_id->addr)) {
1875                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1876                         ZERO_STRUCTP(r->out.handle);
1877                         return WERR_ACCESS_DENIED;
1878                 }
1879
1880                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1881                                    p->session_info->security_token, snum) ||
1882                     !print_access_check(p->session_info,
1883                                         p->msg_ctx,
1884                                         snum,
1885                                         r->in.access_mask)) {
1886                         DEBUG(3, ("access DENIED for printer open\n"));
1887                         close_printer_handle(p, r->out.handle);
1888                         ZERO_STRUCTP(r->out.handle);
1889                         return WERR_ACCESS_DENIED;
1890                 }
1891
1892                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1893                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1894                         close_printer_handle(p, r->out.handle);
1895                         ZERO_STRUCTP(r->out.handle);
1896                         return WERR_ACCESS_DENIED;
1897                 }
1898
1899                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1900                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1901                 else
1902                         r->in.access_mask = PRINTER_ACCESS_USE;
1903
1904                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1905                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1906
1907                 winreg_create_printer(p->mem_ctx,
1908                                       get_session_info_system(),
1909                                       p->msg_ctx,
1910                                       lp_const_servicename(snum));
1911
1912                 break;
1913
1914         default:
1915                 /* sanity check to prevent programmer error */
1916                 ZERO_STRUCTP(r->out.handle);
1917                 return WERR_BADFID;
1918         }
1919
1920         Printer->access_granted = r->in.access_mask;
1921
1922         /*
1923          * If the client sent a devmode in the OpenPrinter() call, then
1924          * save it here in case we get a job submission on this handle
1925          */
1926
1927          if ((Printer->printer_type != SPLHND_SERVER) &&
1928              r->in.devmode_ctr.devmode) {
1929                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1930                                 &Printer->devmode);
1931          }
1932
1933 #if 0   /* JERRY -- I'm doubtful this is really effective */
1934         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1935            optimization in Windows 2000 clients  --jerry */
1936
1937         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1938                 && (RA_WIN2K == get_remote_arch()) )
1939         {
1940                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1941                 sys_usleep( 500000 );
1942         }
1943 #endif
1944
1945         return WERR_OK;
1946 }
1947
1948 /****************************************************************
1949  _spoolss_ClosePrinter
1950 ****************************************************************/
1951
1952 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1953                              struct spoolss_ClosePrinter *r)
1954 {
1955         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1956
1957         if (Printer && Printer->document_started) {
1958                 struct spoolss_EndDocPrinter e;
1959
1960                 e.in.handle = r->in.handle;
1961
1962                 _spoolss_EndDocPrinter(p, &e);
1963         }
1964
1965         if (!close_printer_handle(p, r->in.handle))
1966                 return WERR_BADFID;
1967
1968         /* clear the returned printer handle.  Observed behavior
1969            from Win2k server.  Don't think this really matters.
1970            Previous code just copied the value of the closed
1971            handle.    --jerry */
1972
1973         ZERO_STRUCTP(r->out.handle);
1974
1975         return WERR_OK;
1976 }
1977
1978 /****************************************************************
1979  _spoolss_DeletePrinter
1980 ****************************************************************/
1981
1982 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1983                               struct spoolss_DeletePrinter *r)
1984 {
1985         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1986         WERROR result;
1987         int snum;
1988
1989         if (Printer && Printer->document_started) {
1990                 struct spoolss_EndDocPrinter e;
1991
1992                 e.in.handle = r->in.handle;
1993
1994                 _spoolss_EndDocPrinter(p, &e);
1995         }
1996
1997         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1998                 winreg_delete_printer_key(p->mem_ctx,
1999                                           get_session_info_system(),
2000                                           p->msg_ctx,
2001                                           lp_const_servicename(snum),
2002                                           "");
2003         }
2004
2005         result = delete_printer_handle(p, r->in.handle);
2006
2007         return result;
2008 }
2009
2010 /*******************************************************************
2011  * static function to lookup the version id corresponding to an
2012  * long architecture string
2013  ******************************************************************/
2014
2015 static const struct print_architecture_table_node archi_table[]= {
2016
2017         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2018         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2019         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2020         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2021         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2022         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2023         {"Windows x64",          SPL_ARCH_X64,          3 },
2024         {NULL,                   "",            -1 }
2025 };
2026
2027 static int get_version_id(const char *arch)
2028 {
2029         int i;
2030
2031         for (i=0; archi_table[i].long_archi != NULL; i++)
2032         {
2033                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2034                         return (archi_table[i].version);
2035         }
2036
2037         return -1;
2038 }
2039
2040 /****************************************************************
2041  _spoolss_DeletePrinterDriver
2042 ****************************************************************/
2043
2044 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2045                                     struct spoolss_DeletePrinterDriver *r)
2046 {
2047
2048         struct spoolss_DriverInfo8 *info = NULL;
2049         struct spoolss_DriverInfo8 *info_win2k = NULL;
2050         int                             version;
2051         WERROR                          status;
2052
2053         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2054            and not a printer admin, then fail */
2055
2056         if ( (p->session_info->utok.uid != sec_initial_uid())
2057              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2058                 && !token_contains_name_in_list(
2059                         uidtoname(p->session_info->utok.uid),
2060                         p->session_info->info3->base.domain.string,
2061                         NULL,
2062                         p->session_info->security_token,
2063                         lp_printer_admin(-1)) )
2064         {
2065                 return WERR_ACCESS_DENIED;
2066         }
2067
2068         /* check that we have a valid driver name first */
2069
2070         if ((version = get_version_id(r->in.architecture)) == -1)
2071                 return WERR_INVALID_ENVIRONMENT;
2072
2073         status = winreg_get_driver(p->mem_ctx,
2074                                    get_session_info_system(),
2075                                    p->msg_ctx,
2076                                    r->in.architecture, r->in.driver,
2077                                    version, &info);
2078         if (!W_ERROR_IS_OK(status)) {
2079                 /* try for Win2k driver if "Windows NT x86" */
2080
2081                 if ( version == 2 ) {
2082                         version = 3;
2083
2084                         status = winreg_get_driver(p->mem_ctx,
2085                                                    get_session_info_system(),
2086                                                    p->msg_ctx,
2087                                                    r->in.architecture,
2088                                                    r->in.driver,
2089                                                    version, &info);
2090                         if (!W_ERROR_IS_OK(status)) {
2091                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2092                                 goto done;
2093                         }
2094                 }
2095                 /* otherwise it was a failure */
2096                 else {
2097                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2098                         goto done;
2099                 }
2100
2101         }
2102
2103         if (printer_driver_in_use(p->mem_ctx,
2104                                   get_session_info_system(),
2105                                   p->msg_ctx,
2106                                   info)) {
2107                 status = WERR_PRINTER_DRIVER_IN_USE;
2108                 goto done;
2109         }
2110
2111         if (version == 2) {
2112                 status = winreg_get_driver(p->mem_ctx,
2113                                            get_session_info_system(),
2114                                            p->msg_ctx,
2115                                            r->in.architecture,
2116                                            r->in.driver, 3, &info_win2k);
2117                 if (W_ERROR_IS_OK(status)) {
2118                         /* if we get to here, we now have 2 driver info structures to remove */
2119                         /* remove the Win2k driver first*/
2120
2121                         status = winreg_del_driver(p->mem_ctx,
2122                                                    get_session_info_system(),
2123                                                    p->msg_ctx,
2124                                                    info_win2k, 3);
2125                         talloc_free(info_win2k);
2126
2127                         /* this should not have failed---if it did, report to client */
2128                         if (!W_ERROR_IS_OK(status)) {
2129                                 goto done;
2130                         }
2131                 }
2132         }
2133
2134         status = winreg_del_driver(p->mem_ctx,
2135                                    get_session_info_system(),
2136                                    p->msg_ctx,
2137                                    info, version);
2138
2139 done:
2140         talloc_free(info);
2141
2142         return status;
2143 }
2144
2145 /****************************************************************
2146  _spoolss_DeletePrinterDriverEx
2147 ****************************************************************/
2148
2149 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2150                                       struct spoolss_DeletePrinterDriverEx *r)
2151 {
2152         struct spoolss_DriverInfo8      *info = NULL;
2153         struct spoolss_DriverInfo8      *info_win2k = NULL;
2154         int                             version;
2155         bool                            delete_files;
2156         WERROR                          status;
2157
2158         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2159            and not a printer admin, then fail */
2160
2161         if ( (p->session_info->utok.uid != sec_initial_uid())
2162                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2163                 && !token_contains_name_in_list(
2164                         uidtoname(p->session_info->utok.uid),
2165                         p->session_info->info3->base.domain.string,
2166                         NULL,
2167                         p->session_info->security_token, lp_printer_admin(-1)) )
2168         {
2169                 return WERR_ACCESS_DENIED;
2170         }
2171
2172         /* check that we have a valid driver name first */
2173         if ((version = get_version_id(r->in.architecture)) == -1) {
2174                 /* this is what NT returns */
2175                 return WERR_INVALID_ENVIRONMENT;
2176         }
2177
2178         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2179                 version = r->in.version;
2180
2181         status = winreg_get_driver(p->mem_ctx,
2182                                    get_session_info_system(),
2183                                    p->msg_ctx,
2184                                    r->in.architecture,
2185                                    r->in.driver,
2186                                    version,
2187                                    &info);
2188         if (!W_ERROR_IS_OK(status)) {
2189                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2190
2191                 /*
2192                  * if the client asked for a specific version,
2193                  * or this is something other than Windows NT x86,
2194                  * then we've failed
2195                  */
2196
2197                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2198                         goto done;
2199
2200                 /* try for Win2k driver if "Windows NT x86" */
2201
2202                 version = 3;
2203                 status = winreg_get_driver(info,
2204                                            get_session_info_system(),
2205                                            p->msg_ctx,
2206                                            r->in.architecture,
2207                                            r->in.driver,
2208                                            version, &info);
2209                 if (!W_ERROR_IS_OK(status)) {
2210                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2211                         goto done;
2212                 }
2213         }
2214
2215         if (printer_driver_in_use(info,
2216                                   get_session_info_system(),
2217                                   p->msg_ctx,
2218                                   info)) {
2219                 status = WERR_PRINTER_DRIVER_IN_USE;
2220                 goto done;
2221         }
2222
2223         /*
2224          * we have a couple of cases to consider.
2225          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2226          *     then the delete should fail if **any** files overlap with
2227          *     other drivers
2228          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2229          *     non-overlapping files
2230          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2231          *     is set, the do not delete any files
2232          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2233          */
2234
2235         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2236
2237         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2238
2239         if (delete_files &&
2240             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2241             printer_driver_files_in_use(info,
2242                                         get_session_info_system(),
2243                                         p->msg_ctx,
2244                                         info)) {
2245                 /* no idea of the correct error here */
2246                 status = WERR_ACCESS_DENIED;
2247                 goto done;
2248         }
2249
2250
2251         /* also check for W32X86/3 if necessary; maybe we already have? */
2252
2253         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2254                 status = winreg_get_driver(info,
2255                                            get_session_info_system(),
2256                                            p->msg_ctx,
2257                                            r->in.architecture,
2258                                            r->in.driver, 3, &info_win2k);
2259                 if (W_ERROR_IS_OK(status)) {
2260
2261                         if (delete_files &&
2262                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2263                             printer_driver_files_in_use(info,
2264                                                         get_session_info_system(),
2265                                                         p->msg_ctx,
2266                                                         info_win2k)) {
2267                                 /* no idea of the correct error here */
2268                                 talloc_free(info_win2k);
2269                                 status = WERR_ACCESS_DENIED;
2270                                 goto done;
2271                         }
2272
2273                         /* if we get to here, we now have 2 driver info structures to remove */
2274                         /* remove the Win2k driver first*/
2275
2276                         status = winreg_del_driver(info,
2277                                                    get_session_info_system(),
2278                                                    p->msg_ctx,
2279                                                    info_win2k,
2280                                                    3);
2281
2282                         /* this should not have failed---if it did, report to client */
2283
2284                         if (!W_ERROR_IS_OK(status)) {
2285                                 goto done;
2286                         }
2287
2288                         /*
2289                          * now delete any associated files if delete_files is
2290                          * true. Even if this part failes, we return succes
2291                          * because the driver doesn not exist any more
2292                          */
2293                         if (delete_files) {
2294                                 delete_driver_files(get_session_info_system(),
2295                                                     info_win2k);
2296                         }
2297                 }
2298         }
2299
2300         status = winreg_del_driver(info,
2301                                    get_session_info_system(),
2302                                    p->msg_ctx,
2303                                    info,
2304                                    version);
2305         if (!W_ERROR_IS_OK(status)) {
2306                 goto done;
2307         }
2308
2309         /*
2310          * now delete any associated files if delete_files is
2311          * true. Even if this part failes, we return succes
2312          * because the driver doesn not exist any more
2313          */
2314         if (delete_files) {
2315                 delete_driver_files(get_session_info_system(), info);
2316         }
2317
2318 done:
2319         talloc_free(info);
2320         return status;
2321 }
2322
2323
2324 /********************************************************************
2325  GetPrinterData on a printer server Handle.
2326 ********************************************************************/
2327
2328 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2329                                             const char *value,
2330                                             enum winreg_Type *type,
2331                                             union spoolss_PrinterData *data)
2332 {
2333         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2334
2335         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2336                 *type = REG_DWORD;
2337                 data->value = 0x00;
2338                 return WERR_OK;
2339         }
2340
2341         if (!StrCaseCmp(value, "BeepEnabled")) {
2342                 *type = REG_DWORD;
2343                 data->value = 0x00;
2344                 return WERR_OK;
2345         }
2346
2347         if (!StrCaseCmp(value, "EventLog")) {
2348                 *type = REG_DWORD;
2349                 /* formally was 0x1b */
2350                 data->value = 0x00;
2351                 return WERR_OK;
2352         }
2353
2354         if (!StrCaseCmp(value, "NetPopup")) {
2355                 *type = REG_DWORD;
2356                 data->value = 0x00;
2357                 return WERR_OK;
2358         }
2359
2360         if (!StrCaseCmp(value, "MajorVersion")) {
2361                 *type = REG_DWORD;
2362
2363                 /* Windows NT 4.0 seems to not allow uploading of drivers
2364                    to a server that reports 0x3 as the MajorVersion.
2365                    need to investigate more how Win2k gets around this .
2366                    -- jerry */
2367
2368                 if (RA_WINNT == get_remote_arch()) {
2369                         data->value = 0x02;
2370                 } else {
2371                         data->value = 0x03;
2372                 }
2373
2374                 return WERR_OK;
2375         }
2376
2377         if (!StrCaseCmp(value, "MinorVersion")) {
2378                 *type = REG_DWORD;
2379                 data->value = 0x00;
2380                 return WERR_OK;
2381         }
2382
2383         /* REG_BINARY
2384          *  uint32_t size        = 0x114
2385          *  uint32_t major       = 5
2386          *  uint32_t minor       = [0|1]
2387          *  uint32_t build       = [2195|2600]
2388          *  extra unicode string = e.g. "Service Pack 3"
2389          */
2390         if (!StrCaseCmp(value, "OSVersion")) {
2391                 DATA_BLOB blob;
2392                 enum ndr_err_code ndr_err;
2393                 struct spoolss_OSVersion os;
2394
2395                 os.major                = 5;    /* Windows 2000 == 5.0 */
2396                 os.minor                = 0;
2397                 os.build                = 2195; /* build */
2398                 os.extra_string         = "";   /* leave extra string empty */
2399
2400                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2401                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2402                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2403                         return WERR_GENERAL_FAILURE;
2404                 }
2405
2406                 *type = REG_BINARY;
2407                 data->binary = blob;
2408
2409                 return WERR_OK;
2410         }
2411
2412
2413         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2414                 *type = REG_SZ;
2415
2416                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2417                 W_ERROR_HAVE_NO_MEMORY(data->string);
2418
2419                 return WERR_OK;
2420         }
2421
2422         if (!StrCaseCmp(value, "Architecture")) {
2423                 *type = REG_SZ;
2424                 data->string = talloc_strdup(mem_ctx,
2425                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2426                 W_ERROR_HAVE_NO_MEMORY(data->string);
2427
2428                 return WERR_OK;
2429         }
2430
2431         if (!StrCaseCmp(value, "DsPresent")) {
2432                 *type = REG_DWORD;
2433
2434                 /* only show the publish check box if we are a
2435                    member of a AD domain */
2436
2437                 if (lp_security() == SEC_ADS) {
2438                         data->value = 0x01;
2439                 } else {
2440                         data->value = 0x00;
2441                 }
2442                 return WERR_OK;
2443         }
2444
2445         if (!StrCaseCmp(value, "DNSMachineName")) {
2446                 const char *hostname = get_mydnsfullname();
2447
2448                 if (!hostname) {
2449                         return WERR_BADFILE;
2450                 }
2451
2452                 *type = REG_SZ;
2453                 data->string = talloc_strdup(mem_ctx, hostname);
2454                 W_ERROR_HAVE_NO_MEMORY(data->string);
2455
2456                 return WERR_OK;
2457         }
2458
2459         *type = REG_NONE;
2460
2461         return WERR_INVALID_PARAM;
2462 }
2463
2464 /****************************************************************
2465  _spoolss_GetPrinterData
2466 ****************************************************************/
2467
2468 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2469                                struct spoolss_GetPrinterData *r)
2470 {
2471         struct spoolss_GetPrinterDataEx r2;
2472
2473         r2.in.handle            = r->in.handle;
2474         r2.in.key_name          = "PrinterDriverData";
2475         r2.in.value_name        = r->in.value_name;
2476         r2.in.offered           = r->in.offered;
2477         r2.out.type             = r->out.type;
2478         r2.out.data             = r->out.data;
2479         r2.out.needed           = r->out.needed;
2480
2481         return _spoolss_GetPrinterDataEx(p, &r2);
2482 }
2483
2484 /*********************************************************
2485  Connect to the client machine.
2486 **********************************************************/
2487
2488 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2489                         struct sockaddr_storage *client_ss, const char *remote_machine)
2490 {
2491         NTSTATUS ret;
2492         struct cli_state *the_cli;
2493         struct sockaddr_storage rm_addr;
2494         char addr[INET6_ADDRSTRLEN];
2495
2496         if ( is_zero_addr(client_ss) ) {
2497                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2498                         remote_machine));
2499                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2500                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2501                         return false;
2502                 }
2503                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2504         } else {
2505                 rm_addr = *client_ss;
2506                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2507                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2508                         addr));
2509         }
2510
2511         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2512                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2513                         addr));
2514                 return false;
2515         }
2516
2517         /* setup the connection */
2518         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2519                 &rm_addr, 0, "IPC$", "IPC",
2520                 "", /* username */
2521                 "", /* domain */
2522                 "", /* password */
2523                 0, lp_client_signing());
2524
2525         if ( !NT_STATUS_IS_OK( ret ) ) {
2526                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2527                         remote_machine ));
2528                 return false;
2529         }
2530
2531         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2532                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2533                 cli_shutdown(the_cli);
2534                 return false;
2535         }
2536
2537         /*
2538          * Ok - we have an anonymous connection to the IPC$ share.
2539          * Now start the NT Domain stuff :-).
2540          */
2541
2542         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2543         if (!NT_STATUS_IS_OK(ret)) {
2544                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2545                         remote_machine, nt_errstr(ret)));
2546                 cli_shutdown(the_cli);
2547                 return false;
2548         }
2549
2550         return true;
2551 }
2552
2553 /***************************************************************************
2554  Connect to the client.
2555 ****************************************************************************/
2556
2557 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2558                                         uint32_t localprinter,
2559                                         enum winreg_Type type,
2560                                         struct policy_handle *handle,
2561                                         struct notify_back_channel **_chan,
2562                                         struct sockaddr_storage *client_ss,
2563                                         struct messaging_context *msg_ctx)
2564 {
2565         WERROR result;
2566         NTSTATUS status;
2567         struct notify_back_channel *chan;
2568
2569         for (chan = back_channels; chan; chan = chan->next) {
2570                 if (memcmp(&chan->client_address, client_ss,
2571                            sizeof(struct sockaddr_storage)) == 0) {
2572                         break;
2573                 }
2574         }
2575
2576         /*
2577          * If it's the first connection, contact the client
2578          * and connect to the IPC$ share anonymously
2579          */
2580         if (!chan) {
2581                 fstring unix_printer;
2582
2583                 /* the +2 is to strip the leading 2 backslashs */
2584                 fstrcpy(unix_printer, printer + 2);
2585
2586                 chan = talloc_zero(back_channels, struct notify_back_channel);
2587                 if (!chan) {
2588                         return false;
2589                 }
2590                 chan->client_address = *client_ss;
2591
2592                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2593                         TALLOC_FREE(chan);
2594                         return false;
2595                 }
2596                 chan->binding_handle = chan->cli_pipe->binding_handle;
2597
2598                 DLIST_ADD(back_channels, chan);
2599
2600                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2601                                    receive_notify2_message_list);
2602                 /* Tell the connections db we're now interested in printer
2603                  * notify messages. */
2604                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2605                                             true, FLAG_MSG_PRINT_NOTIFY);
2606         }
2607
2608         /*
2609          * Tell the specific printing tdb we want messages for this printer
2610          * by registering our PID.
2611          */
2612
2613         if (!print_notify_register_pid(snum)) {
2614                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2615                           printer));
2616         }
2617
2618         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2619                                                  talloc_tos(),
2620                                                  printer,
2621                                                  localprinter,
2622                                                  type,
2623                                                  0,
2624                                                  NULL,
2625                                                  handle,
2626                                                  &result);
2627         if (!NT_STATUS_IS_OK(status)) {
2628                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2629                 result = ntstatus_to_werror(status);
2630         } else if (!W_ERROR_IS_OK(result)) {
2631                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2632         }
2633
2634         chan->active_connections++;
2635         *_chan = chan;
2636
2637         return (W_ERROR_IS_OK(result));
2638 }
2639
2640 /****************************************************************
2641  ****************************************************************/
2642
2643 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2644                                                              const struct spoolss_NotifyOption *r)
2645 {
2646         struct spoolss_NotifyOption *option;
2647         uint32_t i,k;
2648
2649         if (!r) {
2650                 return NULL;
2651         }
2652
2653         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2654         if (!option) {
2655                 return NULL;
2656         }
2657
2658         *option = *r;
2659
2660         if (!option->count) {
2661                 return option;
2662         }
2663
2664         option->types = talloc_zero_array(option,
2665                 struct spoolss_NotifyOptionType, option->count);
2666         if (!option->types) {
2667                 talloc_free(option);
2668                 return NULL;
2669         }
2670
2671         for (i=0; i < option->count; i++) {
2672                 option->types[i] = r->types[i];
2673
2674                 if (option->types[i].count) {
2675                         option->types[i].fields = talloc_zero_array(option,
2676                                 union spoolss_Field, option->types[i].count);
2677                         if (!option->types[i].fields) {
2678                                 talloc_free(option);
2679                                 return NULL;
2680                         }
2681                         for (k=0; k<option->types[i].count; k++) {
2682                                 option->types[i].fields[k] =
2683                                         r->types[i].fields[k];
2684                         }
2685                 }
2686         }
2687
2688         return option;
2689 }
2690
2691 /****************************************************************
2692  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2693  *
2694  * before replying OK: status=0 a rpc call is made to the workstation
2695  * asking ReplyOpenPrinter
2696  *
2697  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2698  * called from api_spoolss_rffpcnex
2699 ****************************************************************/
2700
2701 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2702                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2703 {
2704         int snum = -1;
2705         struct spoolss_NotifyOption *option = r->in.notify_options;
2706         struct sockaddr_storage client_ss;
2707
2708         /* store the notify value in the printer struct */
2709
2710         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2711
2712         if (!Printer) {
2713                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714                         "Invalid handle (%s:%u:%u).\n",
2715                         OUR_HANDLE(r->in.handle)));
2716                 return WERR_BADFID;
2717         }
2718
2719         Printer->notify.flags           = r->in.flags;
2720         Printer->notify.options         = r->in.options;
2721         Printer->notify.printerlocal    = r->in.printer_local;
2722         Printer->notify.msg_ctx         = p->msg_ctx;
2723
2724         TALLOC_FREE(Printer->notify.option);
2725         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2726
2727         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2728
2729         /* Connect to the client machine and send a ReplyOpenPrinter */
2730
2731         if ( Printer->printer_type == SPLHND_SERVER)
2732                 snum = -1;
2733         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2734                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2735                 return WERR_BADFID;
2736
2737         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2738                 "client_address is %s\n", p->client_id->addr));
2739
2740         if (!lp_print_notify_backchannel(snum)) {
2741                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2742                         "backchannel disabled\n"));
2743                 return WERR_SERVER_UNAVAILABLE;
2744         }
2745
2746         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2747                                    AI_NUMERICHOST)) {
2748                 return WERR_SERVER_UNAVAILABLE;
2749         }
2750
2751         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2752                                         Printer->notify.printerlocal, REG_SZ,
2753                                         &Printer->notify.cli_hnd,
2754                                         &Printer->notify.cli_chan,
2755                                         &client_ss, p->msg_ctx)) {
2756                 return WERR_SERVER_UNAVAILABLE;
2757         }
2758
2759         return WERR_OK;
2760 }
2761
2762 /*******************************************************************
2763  * fill a notify_info_data with the servername
2764  ********************************************************************/
2765
2766 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2767                                        int snum,
2768                                        struct spoolss_Notify *data,
2769                                        print_queue_struct *queue,
2770                                        struct spoolss_PrinterInfo2 *pinfo2,
2771                                        TALLOC_CTX *mem_ctx)
2772 {
2773         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2774 }
2775
2776 /*******************************************************************
2777  * fill a notify_info_data with the printername (not including the servername).
2778  ********************************************************************/
2779
2780 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2781                                         int snum,
2782                                         struct spoolss_Notify *data,
2783                                         print_queue_struct *queue,
2784                                         struct spoolss_PrinterInfo2 *pinfo2,
2785                                         TALLOC_CTX *mem_ctx)
2786 {
2787         /* the notify name should not contain the \\server\ part */
2788         const char *p = strrchr(pinfo2->printername, '\\');
2789
2790         if (!p) {
2791                 p = pinfo2->printername;
2792         } else {
2793                 p++;
2794         }
2795
2796         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2797 }
2798
2799 /*******************************************************************
2800  * fill a notify_info_data with the servicename
2801  ********************************************************************/
2802
2803 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2804                                       int snum,
2805                                       struct spoolss_Notify *data,
2806                                       print_queue_struct *queue,
2807                                       struct spoolss_PrinterInfo2 *pinfo2,
2808                                       TALLOC_CTX *mem_ctx)
2809 {
2810         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2811 }
2812
2813 /*******************************************************************
2814  * fill a notify_info_data with the port name
2815  ********************************************************************/
2816
2817 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2818                                      int snum,
2819                                      struct spoolss_Notify *data,
2820                                      print_queue_struct *queue,
2821                                      struct spoolss_PrinterInfo2 *pinfo2,
2822                                      TALLOC_CTX *mem_ctx)
2823 {
2824         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2825 }
2826
2827 /*******************************************************************
2828  * fill a notify_info_data with the printername
2829  * but it doesn't exist, have to see what to do
2830  ********************************************************************/
2831
2832 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2833                                        int snum,
2834                                        struct spoolss_Notify *data,
2835                                        print_queue_struct *queue,
2836                                        struct spoolss_PrinterInfo2 *pinfo2,
2837                                        TALLOC_CTX *mem_ctx)
2838 {
2839         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2840 }
2841
2842 /*******************************************************************
2843  * fill a notify_info_data with the comment
2844  ********************************************************************/
2845
2846 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2847                                    int snum,
2848                                    struct spoolss_Notify *data,
2849                                    print_queue_struct *queue,
2850                                    struct spoolss_PrinterInfo2 *pinfo2,
2851                                    TALLOC_CTX *mem_ctx)
2852 {
2853         const char *p;
2854
2855         if (*pinfo2->comment == '\0') {
2856                 p = lp_comment(snum);
2857         } else {
2858                 p = pinfo2->comment;
2859         }
2860
2861         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2862 }
2863
2864 /*******************************************************************
2865  * fill a notify_info_data with the comment
2866  * location = "Room 1, floor 2, building 3"
2867  ********************************************************************/
2868
2869 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2870                                     int snum,
2871                                     struct spoolss_Notify *data,
2872                                     print_queue_struct *queue,
2873                                     struct spoolss_PrinterInfo2 *pinfo2,
2874                                     TALLOC_CTX *mem_ctx)
2875 {
2876         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2877 }
2878
2879 /*******************************************************************
2880  * fill a notify_info_data with the device mode
2881  * jfm:xxxx don't to it for know but that's a real problem !!!
2882  ********************************************************************/
2883
2884 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2885                                    int snum,
2886                                    struct spoolss_Notify *data,
2887                                    print_queue_struct *queue,
2888                                    struct spoolss_PrinterInfo2 *pinfo2,
2889                                    TALLOC_CTX *mem_ctx)
2890 {
2891         /* for a dummy implementation we have to zero the fields */
2892         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2893 }
2894
2895 /*******************************************************************
2896  * fill a notify_info_data with the separator file name
2897  ********************************************************************/
2898
2899 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2900                                    int snum,
2901                                    struct spoolss_Notify *data,
2902                                    print_queue_struct *queue,
2903                                    struct spoolss_PrinterInfo2 *pinfo2,
2904                                    TALLOC_CTX *mem_ctx)
2905 {
2906         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2907 }
2908
2909 /*******************************************************************
2910  * fill a notify_info_data with the print processor
2911  * jfm:xxxx return always winprint to indicate we don't do anything to it
2912  ********************************************************************/
2913
2914 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2915                                            int snum,
2916                                            struct spoolss_Notify *data,
2917                                            print_queue_struct *queue,
2918                                            struct spoolss_PrinterInfo2 *pinfo2,
2919                                            TALLOC_CTX *mem_ctx)
2920 {
2921         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2922 }
2923
2924 /*******************************************************************
2925  * fill a notify_info_data with the print processor options
2926  * jfm:xxxx send an empty string
2927  ********************************************************************/
2928
2929 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2930                                       int snum,
2931                                       struct spoolss_Notify *data,
2932                                       print_queue_struct *queue,
2933                                       struct spoolss_PrinterInfo2 *pinfo2,
2934                                       TALLOC_CTX *mem_ctx)
2935 {
2936         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2937 }
2938
2939 /*******************************************************************
2940  * fill a notify_info_data with the data type
2941  * jfm:xxxx always send RAW as data type
2942  ********************************************************************/
2943
2944 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2945                                     int snum,
2946                                     struct spoolss_Notify *data,
2947                                     print_queue_struct *queue,
2948                                     struct spoolss_PrinterInfo2 *pinfo2,
2949                                     TALLOC_CTX *mem_ctx)
2950 {
2951         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2952 }
2953
2954 /*******************************************************************
2955  * fill a notify_info_data with the security descriptor
2956  * jfm:xxxx send an null pointer to say no security desc
2957  * have to implement security before !
2958  ********************************************************************/
2959
2960 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2961                                          int snum,
2962                                          struct spoolss_Notify *data,
2963                                          print_queue_struct *queue,
2964                                          struct spoolss_PrinterInfo2 *pinfo2,
2965                                          TALLOC_CTX *mem_ctx)
2966 {
2967         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2968 }
2969
2970 /*******************************************************************
2971  * fill a notify_info_data with the attributes
2972  * jfm:xxxx a samba printer is always shared
2973  ********************************************************************/
2974
2975 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2976                                       int snum,
2977                                       struct spoolss_Notify *data,
2978                                       print_queue_struct *queue,
2979                                       struct spoolss_PrinterInfo2 *pinfo2,
2980                                       TALLOC_CTX *mem_ctx)
2981 {
2982         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2983 }
2984
2985 /*******************************************************************
2986  * fill a notify_info_data with the priority
2987  ********************************************************************/
2988
2989 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2990                                     int snum,
2991                                     struct spoolss_Notify *data,
2992                                     print_queue_struct *queue,
2993                                     struct spoolss_PrinterInfo2 *pinfo2,
2994                                     TALLOC_CTX *mem_ctx)
2995 {
2996         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2997 }
2998
2999 /*******************************************************************
3000  * fill a notify_info_data with the default priority
3001  ********************************************************************/
3002
3003 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3004                                             int snum,
3005                                             struct spoolss_Notify *data,
3006                                             print_queue_struct *queue,
3007                                             struct spoolss_PrinterInfo2 *pinfo2,
3008                                             TALLOC_CTX *mem_ctx)
3009 {
3010         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3011 }
3012
3013 /*******************************************************************
3014  * fill a notify_info_data with the start time
3015  ********************************************************************/
3016
3017 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3018                                       int snum,
3019                                       struct spoolss_Notify *data,
3020                                       print_queue_struct *queue,
3021                                       struct spoolss_PrinterInfo2 *pinfo2,
3022                                       TALLOC_CTX *mem_ctx)
3023 {
3024         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3025 }
3026
3027 /*******************************************************************
3028  * fill a notify_info_data with the until time
3029  ********************************************************************/
3030
3031 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3032                                       int snum,
3033                                       struct spoolss_Notify *data,
3034                                       print_queue_struct *queue,
3035                                       struct spoolss_PrinterInfo2 *pinfo2,
3036                                       TALLOC_CTX *mem_ctx)
3037 {
3038         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3039 }
3040
3041 /*******************************************************************
3042  * fill a notify_info_data with the status
3043  ********************************************************************/
3044
3045 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3046                                   int snum,
3047                                   struct spoolss_Notify *data,
3048                                   print_queue_struct *queue,
3049                                   struct spoolss_PrinterInfo2 *pinfo2,
3050                                   TALLOC_CTX *mem_ctx)
3051 {
3052         print_status_struct status;
3053
3054         print_queue_length(msg_ctx, snum, &status);
3055         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3056 }
3057
3058 /*******************************************************************
3059  * fill a notify_info_data with the number of jobs queued
3060  ********************************************************************/
3061
3062 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3063                                  int snum,
3064                                  struct spoolss_Notify *data,
3065                                  print_queue_struct *queue,
3066                                  struct spoolss_PrinterInfo2 *pinfo2,
3067                                  TALLOC_CTX *mem_ctx)
3068 {
3069         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3070                 data, print_queue_length(msg_ctx, snum, NULL));
3071 }
3072
3073 /*******************************************************************
3074  * fill a notify_info_data with the average ppm
3075  ********************************************************************/
3076
3077 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3078                                        int snum,
3079                                        struct spoolss_Notify *data,
3080                                        print_queue_struct *queue,
3081                                        struct spoolss_PrinterInfo2 *pinfo2,
3082                                        TALLOC_CTX *mem_ctx)
3083 {
3084         /* always respond 8 pages per minutes */
3085         /* a little hard ! */
3086         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3087 }
3088
3089 /*******************************************************************
3090  * fill a notify_info_data with username
3091  ********************************************************************/
3092
3093 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3094                                     int snum,
3095                                     struct spoolss_Notify *data,
3096                                     print_queue_struct *queue,
3097                                     struct spoolss_PrinterInfo2 *pinfo2,
3098                                     TALLOC_CTX *mem_ctx)
3099 {
3100         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3101 }
3102
3103 /*******************************************************************
3104  * fill a notify_info_data with job status
3105  ********************************************************************/
3106
3107 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3108                                       int snum,
3109                                       struct spoolss_Notify *data,
3110                                       print_queue_struct *queue,
3111                                       struct spoolss_PrinterInfo2 *pinfo2,
3112                                       TALLOC_CTX *mem_ctx)
3113 {
3114         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3115 }
3116
3117 /*******************************************************************
3118  * fill a notify_info_data with job name
3119  ********************************************************************/
3120
3121 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3122                                     int snum,
3123                                     struct spoolss_Notify *data,
3124                                     print_queue_struct *queue,
3125                                     struct spoolss_PrinterInfo2 *pinfo2,
3126                                     TALLOC_CTX *mem_ctx)
3127 {
3128         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3129 }
3130
3131 /*******************************************************************
3132  * fill a notify_info_data with job status
3133  ********************************************************************/
3134
3135 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3136                                              int snum,
3137                                              struct spoolss_Notify *data,
3138                                              print_queue_struct *queue,
3139                                              struct spoolss_PrinterInfo2 *pinfo2,
3140                                              TALLOC_CTX *mem_ctx)
3141 {
3142         /*
3143          * Now we're returning job status codes we just return a "" here. JRA.
3144          */
3145
3146         const char *p = "";
3147
3148 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3149         p = "unknown";
3150
3151         switch (queue->status) {
3152         case LPQ_QUEUED:
3153                 p = "Queued";
3154                 break;
3155         case LPQ_PAUSED:
3156                 p = "";    /* NT provides the paused string */
3157                 break;
3158         case LPQ_SPOOLING:
3159                 p = "Spooling";
3160                 break;
3161         case LPQ_PRINTING:
3162                 p = "Printing";
3163                 break;
3164         }
3165 #endif /* NO LONGER NEEDED. */
3166
3167         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3168 }
3169
3170 /*******************************************************************
3171  * fill a notify_info_data with job time
3172  ********************************************************************/
3173
3174 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3175                                     int snum,
3176                                     struct spoolss_Notify *data,
3177                                     print_queue_struct *queue,
3178                                     struct spoolss_PrinterInfo2 *pinfo2,
3179                                     TALLOC_CTX *mem_ctx)
3180 {
3181         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3182 }
3183
3184 /*******************************************************************
3185  * fill a notify_info_data with job size
3186  ********************************************************************/
3187
3188 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3189                                     int snum,
3190                                     struct spoolss_Notify *data,
3191                                     print_queue_struct *queue,
3192                                     struct spoolss_PrinterInfo2 *pinfo2,
3193                                     TALLOC_CTX *mem_ctx)
3194 {
3195         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3196 }
3197
3198 /*******************************************************************
3199  * fill a notify_info_data with page info
3200  ********************************************************************/
3201 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3202                                        int snum,
3203                                 struct spoolss_Notify *data,
3204                                 print_queue_struct *queue,
3205                                 struct spoolss_PrinterInfo2 *pinfo2,
3206                                 TALLOC_CTX *mem_ctx)
3207 {
3208         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3209 }
3210
3211 /*******************************************************************
3212  * fill a notify_info_data with pages printed info.
3213  ********************************************************************/
3214 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3215                                          int snum,
3216                                 struct spoolss_Notify *data,
3217                                 print_queue_struct *queue,
3218                                 struct spoolss_PrinterInfo2 *pinfo2,
3219                                 TALLOC_CTX *mem_ctx)
3220 {
3221         /* Add code when back-end tracks this */
3222         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3223 }
3224
3225 /*******************************************************************
3226  Fill a notify_info_data with job position.
3227  ********************************************************************/
3228
3229 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3230                                         int snum,
3231                                         struct spoolss_Notify *data,
3232                                         print_queue_struct *queue,
3233                                         struct spoolss_PrinterInfo2 *pinfo2,
3234                                         TALLOC_CTX *mem_ctx)
3235 {
3236         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3237 }
3238
3239 /*******************************************************************
3240  Fill a notify_info_data with submitted time.
3241  ********************************************************************/
3242
3243 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3244                                           int snum,
3245                                           struct spoolss_Notify *data,
3246                                           print_queue_struct *queue,
3247                                           struct spoolss_PrinterInfo2 *pinfo2,
3248                                           TALLOC_CTX *mem_ctx)
3249 {
3250         data->data.string.string = NULL;
3251         data->data.string.size = 0;
3252
3253         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3254                                &data->data.string.string,
3255                                &data->data.string.size);
3256
3257 }
3258
3259 struct s_notify_info_data_table
3260 {
3261         enum spoolss_NotifyType type;
3262         uint16_t field;
3263         const char *name;
3264         enum spoolss_NotifyTable variable_type;
3265         void (*fn) (struct messaging_context *msg_ctx,
3266                     int snum, struct spoolss_Notify *data,
3267                     print_queue_struct *queue,
3268                     struct spoolss_PrinterInfo2 *pinfo2,
3269                     TALLOC_CTX *mem_ctx);
3270 };
3271
3272 /* A table describing the various print notification constants and
3273    whether the notification data is a pointer to a variable sized
3274    buffer, a one value uint32_t or a two value uint32_t. */
3275
3276 static const struct s_notify_info_data_table notify_info_data_table[] =
3277 {
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3327 };
3328
3329 /*******************************************************************
3330  Return the variable_type of info_data structure.
3331 ********************************************************************/
3332
3333 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3334                                                                   uint16_t field)
3335 {
3336         int i=0;
3337
3338         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3339                 if ( (notify_info_data_table[i].type == type) &&
3340                      (notify_info_data_table[i].field == field) ) {
3341                         return notify_info_data_table[i].variable_type;
3342                 }
3343         }
3344
3345         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3346
3347         return (enum spoolss_NotifyTable) 0;
3348 }
3349
3350 /****************************************************************************
3351 ****************************************************************************/
3352
3353 static bool search_notify(enum spoolss_NotifyType type,
3354                           uint16_t field,
3355                           int *value)
3356 {
3357         int i;
3358
3359         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3360                 if (notify_info_data_table[i].type == type &&
3361                     notify_info_data_table[i].field == field &&
3362                     notify_info_data_table[i].fn != NULL) {
3363                         *value = i;
3364                         return true;
3365                 }
3366         }
3367
3368         return false;
3369 }
3370
3371 /****************************************************************************
3372 ****************************************************************************/
3373
3374 static void construct_info_data(struct spoolss_Notify *info_data,
3375                                 enum spoolss_NotifyType type,
3376                                 uint16_t field, int id)
3377 {
3378         info_data->type                 = type;
3379         info_data->field.field          = field;
3380         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3381         info_data->job_id               = id;
3382 }
3383
3384 /*******************************************************************
3385  *
3386  * fill a notify_info struct with info asked
3387  *
3388  ********************************************************************/
3389
3390 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3391                                           struct printer_handle *print_hnd,
3392                                           struct spoolss_NotifyInfo *info,
3393                                           struct spoolss_PrinterInfo2 *pinfo2,
3394                                           int snum,
3395                                           const struct spoolss_NotifyOptionType *option_type,
3396                                           uint32_t id,
3397                                           TALLOC_CTX *mem_ctx)
3398 {
3399         int field_num,j;
3400         enum spoolss_NotifyType type;
3401         uint16_t field;
3402
3403         struct spoolss_Notify *current_data;
3404         print_queue_struct *queue=NULL;
3405
3406         type = option_type->type;
3407
3408         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3409                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3410                 option_type->count, lp_servicename(snum)));
3411
3412         for(field_num=0; field_num < option_type->count; field_num++) {
3413                 field = option_type->fields[field_num].field;
3414
3415                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3416
3417                 if (!search_notify(type, field, &j) )
3418                         continue;
3419
3420                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3421                                                       struct spoolss_Notify,
3422                                                       info->count + 1);
3423                 if (info->notifies == NULL) {
3424                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3425                         return false;
3426                 }
3427
3428                 current_data = &info->notifies[info->count];
3429
3430                 construct_info_data(current_data, type, field, id);
3431
3432                 DEBUG(10, ("construct_notify_printer_info: "
3433                            "calling [%s]  snum=%d  printername=[%s])\n",
3434                            notify_info_data_table[j].name, snum,
3435                            pinfo2->printername));
3436
3437                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3438                                              queue, pinfo2, mem_ctx);
3439
3440                 info->count++;
3441         }
3442
3443         return true;
3444 }
3445
3446 /*******************************************************************
3447  *
3448  * fill a notify_info struct with info asked
3449  *
3450  ********************************************************************/
3451
3452 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3453                                        print_queue_struct *queue,
3454                                        struct spoolss_NotifyInfo *info,
3455                                        struct spoolss_PrinterInfo2 *pinfo2,
3456                                        int snum,
3457                                        const struct spoolss_NotifyOptionType *option_type,
3458                                        uint32_t id,
3459                                        TALLOC_CTX *mem_ctx)
3460 {
3461         int field_num,j;
3462         enum spoolss_NotifyType type;
3463         uint16_t field;
3464         struct spoolss_Notify *current_data;
3465
3466         DEBUG(4,("construct_notify_jobs_info\n"));
3467
3468         type = option_type->type;
3469
3470         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3471                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3472                 option_type->count));
3473
3474         for(field_num=0; field_num<option_type->count; field_num++) {
3475                 field = option_type->fields[field_num].field;
3476
3477                 if (!search_notify(type, field, &j) )
3478                         continue;
3479
3480                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3481                                                       struct spoolss_Notify,
3482                                                       info->count + 1);
3483                 if (info->notifies == NULL) {
3484                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3485                         return false;
3486                 }
3487
3488                 current_data=&(info->notifies[info->count]);
3489
3490                 construct_info_data(current_data, type, field, id);
3491                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3492                                              queue, pinfo2, mem_ctx);
3493                 info->count++;
3494         }
3495
3496         return true;
3497 }
3498
3499 /*
3500  * JFM: The enumeration is not that simple, it's even non obvious.
3501  *
3502  * let's take an example: I want to monitor the PRINTER SERVER for
3503  * the printer's name and the number of jobs currently queued.
3504  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3505  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3506  *
3507  * I have 3 printers on the back of my server.
3508  *
3509  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3510  * structures.
3511  *   Number     Data                    Id
3512  *      1       printer 1 name          1
3513  *      2       printer 1 cjob          1
3514  *      3       printer 2 name          2
3515  *      4       printer 2 cjob          2
3516  *      5       printer 3 name          3
3517  *      6       printer 3 name          3
3518  *
3519  * that's the print server case, the printer case is even worse.
3520  */
3521
3522 /*******************************************************************
3523  *
3524  * enumerate all printers on the printserver
3525  * fill a notify_info struct with info asked
3526  *
3527  ********************************************************************/
3528
3529 static WERROR printserver_notify_info(struct pipes_struct *p,
3530                                       struct policy_handle *hnd,
3531                                       struct spoolss_NotifyInfo *info,
3532                                       TALLOC_CTX *mem_ctx)
3533 {
3534         int snum;
3535         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3536         int n_services=lp_numservices();
3537         int i;
3538         struct spoolss_NotifyOption *option;
3539         struct spoolss_NotifyOptionType option_type;
3540         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3541         WERROR result;
3542
3543         DEBUG(4,("printserver_notify_info\n"));
3544
3545         if (!Printer)
3546                 return WERR_BADFID;
3547
3548         option = Printer->notify.option;
3549
3550         info->version   = 2;
3551         info->notifies  = NULL;
3552         info->count     = 0;
3553
3554         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3555            sending a ffpcn() request first */
3556
3557         if ( !option )
3558                 return WERR_BADFID;
3559
3560         for (i=0; i<option->count; i++) {
3561                 option_type = option->types[i];
3562
3563                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3564                         continue;
3565
3566                 for (snum = 0; snum < n_services; snum++) {
3567                         if (!lp_browseable(snum) ||
3568                             !lp_snum_ok(snum) ||
3569                             !lp_print_ok(snum)) {
3570                                 continue; /* skip */
3571                         }
3572
3573                         /* Maybe we should use the SYSTEM session_info here... */
3574                         result = winreg_get_printer(mem_ctx,
3575                                                     get_session_info_system(),
3576                                                     p->msg_ctx,
3577                                                     lp_servicename(snum),
3578                                                     &pinfo2);
3579                         if (!W_ERROR_IS_OK(result)) {
3580                                 DEBUG(4, ("printserver_notify_info: "
3581                                           "Failed to get printer [%s]\n",
3582                                           lp_servicename(snum)));
3583                                 continue;
3584                         }
3585
3586
3587                         construct_notify_printer_info(p->msg_ctx,
3588                                                       Printer, info,
3589                                                       pinfo2, snum,
3590                                                       &option_type, snum,
3591                                                       mem_ctx);
3592
3593                         TALLOC_FREE(pinfo2);
3594                 }
3595         }
3596
3597 #if 0
3598         /*
3599          * Debugging information, don't delete.
3600          */
3601
3602         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3603         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3604         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3605
3606         for (i=0; i<info->count; i++) {
3607                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3608                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3609                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3610         }
3611 #endif
3612
3613         return WERR_OK;
3614 }
3615
3616 /*******************************************************************
3617  *
3618  * fill a notify_info struct with info asked
3619  *
3620  ********************************************************************/
3621
3622 static WERROR printer_notify_info(struct pipes_struct *p,
3623                                   struct policy_handle *hnd,
3624                                   struct spoolss_NotifyInfo *info,
3625                                   TALLOC_CTX *mem_ctx)
3626 {
3627         int snum;
3628         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3629         int i;
3630         uint32_t id;
3631         struct spoolss_NotifyOption *option;
3632         struct spoolss_NotifyOptionType option_type;
3633         int count,j;
3634         print_queue_struct *queue=NULL;
3635         print_status_struct status;
3636         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3637         WERROR result;
3638
3639         DEBUG(4,("printer_notify_info\n"));
3640
3641         if (!Printer)
3642                 return WERR_BADFID;
3643
3644         option = Printer->notify.option;
3645         id = 0x0;
3646
3647         info->version   = 2;
3648         info->notifies  = NULL;
3649         info->count     = 0;
3650
3651         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3652            sending a ffpcn() request first */
3653
3654         if ( !option )
3655                 return WERR_BADFID;
3656
3657         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3658                 return WERR_BADFID;
3659         }
3660
3661         /* Maybe we should use the SYSTEM session_info here... */
3662         result = winreg_get_printer(mem_ctx,
3663                                     get_session_info_system(),
3664                                     p->msg_ctx,
3665                                     lp_servicename(snum), &pinfo2);
3666         if (!W_ERROR_IS_OK(result)) {
3667                 return WERR_BADFID;
3668         }
3669
3670         for (i=0; i<option->count; i++) {
3671                 option_type = option->types[i];
3672
3673                 switch (option_type.type) {
3674                 case PRINTER_NOTIFY_TYPE:
3675                         if (construct_notify_printer_info(p->msg_ctx,
3676                                                           Printer, info,
3677                                                           pinfo2, snum,
3678                                                           &option_type, id,
3679                                                           mem_ctx)) {
3680                                 id--;
3681                         }
3682                         break;
3683
3684                 case JOB_NOTIFY_TYPE:
3685
3686                         count = print_queue_status(p->msg_ctx, snum, &queue,
3687                                                    &status);
3688
3689                         for (j=0; j<count; j++) {
3690                                 construct_notify_jobs_info(p->msg_ctx,
3691                                                            &queue[j], info,
3692                                                            pinfo2, snum,
3693                                                            &option_type,
3694                                                            queue[j].job,
3695                                                            mem_ctx);
3696                         }
3697
3698                         SAFE_FREE(queue);
3699                         break;
3700                 }
3701         }
3702
3703         /*
3704          * Debugging information, don't delete.
3705          */
3706         /*
3707         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3708         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3709         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3710
3711         for (i=0; i<info->count; i++) {
3712                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3713                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3714                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3715         }
3716         */
3717
3718         talloc_free(pinfo2);
3719         return WERR_OK;
3720 }
3721
3722 /****************************************************************
3723  _spoolss_RouterRefreshPrinterChangeNotify
3724 ****************************************************************/
3725
3726 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3727                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3728 {
3729         struct spoolss_NotifyInfo *info;
3730
3731         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3732         WERROR result = WERR_BADFID;
3733
3734         /* we always have a spoolss_NotifyInfo struct */
3735         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3736         if (!info) {
3737                 result = WERR_NOMEM;
3738                 goto done;
3739         }
3740
3741         *r->out.info = info;
3742
3743         if (!Printer) {
3744                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3745                         "Invalid handle (%s:%u:%u).\n",
3746                         OUR_HANDLE(r->in.handle)));
3747                 goto done;
3748         }
3749
3750         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3751
3752         /*
3753          *      We are now using the change value, and
3754          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3755          *      I don't have a global notification system, I'm sending back all the
3756          *      information even when _NOTHING_ has changed.
3757          */
3758
3759         /* We need to keep track of the change value to send back in
3760            RRPCN replies otherwise our updates are ignored. */
3761
3762         Printer->notify.fnpcn = true;
3763
3764         if (Printer->notify.cli_chan != NULL &&
3765             Printer->notify.cli_chan->active_connections > 0) {
3766                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3767                         "Saving change value in request [%x]\n",
3768                         r->in.change_low));
3769                 Printer->notify.change = r->in.change_low;
3770         }
3771
3772         /* just ignore the spoolss_NotifyOption */
3773
3774         switch (Printer->printer_type) {
3775                 case SPLHND_SERVER:
3776                         result = printserver_notify_info(p, r->in.handle,
3777                                                          info, p->mem_ctx);
3778                         break;
3779
3780                 case SPLHND_PRINTER:
3781                         result = printer_notify_info(p, r->in.handle,
3782                                                      info, p->mem_ctx);
3783                         break;
3784         }
3785
3786         Printer->notify.fnpcn = false;
3787
3788 done:
3789         return result;
3790 }
3791
3792 /********************************************************************
3793  ********************************************************************/
3794
3795 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3796                                  const char *servername,
3797                                  const char *printername,
3798                                  const char **printername_p)
3799 {
3800         /* FIXME: add lp_force_printername() */
3801
3802         if (servername == NULL) {
3803                 *printername_p = talloc_strdup(mem_ctx, printername);
3804                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3805                 return WERR_OK;
3806         }
3807
3808         if (servername[0] == '\\' && servername[1] == '\\') {
3809                 servername += 2;
3810         }
3811
3812         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3813         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3814
3815         return WERR_OK;
3816 }
3817
3818 /********************************************************************
3819  ********************************************************************/
3820
3821 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3822                                           const char *printername)
3823 {
3824         if (dm == NULL) {
3825                 return;
3826         }
3827
3828         dm->devicename = talloc_strndup(dm, printername,
3829                                         MIN(strlen(printername), 31));
3830 }
3831
3832 /********************************************************************
3833  * construct_printer_info_0
3834  * fill a printer_info_0 struct
3835  ********************************************************************/
3836
3837 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3838                                       const struct auth_serversupplied_info *session_info,
3839                                       struct messaging_context *msg_ctx,
3840                                       struct spoolss_PrinterInfo2 *info2,
3841                                       const char *servername,
3842                                       struct spoolss_PrinterInfo0 *r,
3843                                       int snum)
3844 {
3845         int count;
3846         struct printer_session_counter *session_counter;
3847         struct timeval setuptime;
3848         print_status_struct status;
3849         WERROR result;
3850
3851         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3852         if (!W_ERROR_IS_OK(result)) {
3853                 return result;
3854         }
3855
3856         if (servername) {
3857                 r->servername = talloc_strdup(mem_ctx, servername);
3858                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3859         } else {
3860                 r->servername = NULL;
3861         }
3862
3863         count = print_queue_length(msg_ctx, snum, &status);
3864
3865         /* check if we already have a counter for this printer */
3866         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3867                 if (session_counter->snum == snum)
3868                         break;
3869         }
3870
3871         /* it's the first time, add it to the list */
3872         if (session_counter == NULL) {
3873                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3874                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3875                 session_counter->snum           = snum;
3876                 session_counter->counter        = 0;
3877                 DLIST_ADD(counter_list, session_counter);
3878         }
3879
3880         /* increment it */
3881         session_counter->counter++;
3882
3883         r->cjobs                        = count;
3884         r->total_jobs                   = 0;
3885         r->total_bytes                  = 0;
3886
3887         get_startup_time(&setuptime);
3888         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3889
3890         /* JFM:
3891          * the global_counter should be stored in a TDB as it's common to all the clients
3892          * and should be zeroed on samba startup
3893          */
3894         r->global_counter               = session_counter->counter;
3895         r->total_pages                  = 0;
3896         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3897         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3898         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3899         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3900         r->spooling                     = 0;
3901         r->max_spooling                 = 0;
3902         r->session_counter              = session_counter->counter;
3903         r->num_error_out_of_paper       = 0x0;
3904         r->num_error_not_ready          = 0x0;          /* number of print failure */
3905         r->job_error                    = 0x0;
3906         r->number_of_processors         = 0x1;
3907         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3908         r->high_part_total_bytes        = 0x0;
3909
3910         /* ChangeID in milliseconds*/
3911         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3912                                     info2->sharename, &r->change_id);
3913
3914         r->last_error                   = WERR_OK;
3915         r->status                       = nt_printq_status(status.status);
3916         r->enumerate_network_printers   = 0x0;
3917         r->c_setprinter                 = 0x0;
3918         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3919         r->processor_level              = 0x6;          /* 6  ???*/
3920         r->ref_ic                       = 0;
3921         r->reserved2                    = 0;
3922         r->reserved3                    = 0;
3923
3924         return WERR_OK;
3925 }
3926
3927
3928 /********************************************************************
3929  * construct_printer_info1
3930  * fill a spoolss_PrinterInfo1 struct
3931 ********************************************************************/
3932
3933 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3934                                       const struct spoolss_PrinterInfo2 *info2,
3935                                       uint32_t flags,
3936                                       const char *servername,
3937                                       struct spoolss_PrinterInfo1 *r,
3938                                       int snum)
3939 {
3940         WERROR result;
3941
3942         r->flags                = flags;
3943
3944         if (info2->comment == NULL || info2->comment[0] == '\0') {
3945                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3946         } else {
3947                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3948         }
3949         W_ERROR_HAVE_NO_MEMORY(r->comment);
3950
3951         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3952         if (!W_ERROR_IS_OK(result)) {
3953                 return result;
3954         }
3955
3956         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3957                                                   r->name,
3958                                                   info2->drivername,
3959                                                   r->comment);
3960         W_ERROR_HAVE_NO_MEMORY(r->description);
3961
3962         return WERR_OK;
3963 }
3964
3965 /********************************************************************
3966  * construct_printer_info2
3967  * fill a spoolss_PrinterInfo2 struct
3968 ********************************************************************/
3969
3970 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3971                                       struct messaging_context *msg_ctx,
3972                                       const struct spoolss_PrinterInfo2 *info2,
3973                                       const char *servername,
3974                                       struct spoolss_PrinterInfo2 *r,
3975                                       int snum)
3976 {
3977         int count;
3978         print_status_struct status;
3979         WERROR result;
3980
3981         count = print_queue_length(msg_ctx, snum, &status);
3982
3983         if (servername) {
3984                 r->servername           = talloc_strdup(mem_ctx, servername);
3985                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3986         } else {
3987                 r->servername           = NULL;
3988         }
3989
3990         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3991         if (!W_ERROR_IS_OK(result)) {
3992                 return result;
3993         }
3994
3995         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3996         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3997         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3998         W_ERROR_HAVE_NO_MEMORY(r->portname);
3999         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4000         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4001
4002         if (info2->comment[0] == '\0') {
4003                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4004         } else {
4005                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4006         }
4007         W_ERROR_HAVE_NO_MEMORY(r->comment);
4008
4009         r->location             = talloc_strdup(mem_ctx, info2->location);
4010         W_ERROR_HAVE_NO_MEMORY(r->location);
4011         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4012         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4013         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4014         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4015         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4016         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4017         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4018         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4019
4020         r->attributes           = info2->attributes;
4021
4022         r->priority             = info2->priority;
4023         r->defaultpriority      = info2->defaultpriority;
4024         r->starttime            = info2->starttime;
4025         r->untiltime            = info2->untiltime;
4026         r->status               = nt_printq_status(status.status);
4027         r->cjobs                = count;
4028         r->averageppm           = info2->averageppm;
4029
4030         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4031         if (!r->devmode) {
4032                 DEBUG(8,("Returning NULL Devicemode!\n"));
4033         }
4034
4035         compose_devicemode_devicename(r->devmode, r->printername);
4036
4037         r->secdesc = NULL;
4038
4039         if (info2->secdesc != NULL) {
4040                 /* don't use talloc_steal() here unless you do a deep steal of all
4041                    the SEC_DESC members */
4042
4043                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4044         }
4045
4046         return WERR_OK;
4047 }
4048
4049 /********************************************************************
4050  * construct_printer_info3
4051  * fill a spoolss_PrinterInfo3 struct
4052  ********************************************************************/
4053
4054 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4055                                       const struct spoolss_PrinterInfo2 *info2,
4056                                       const char *servername,
4057                                       struct spoolss_PrinterInfo3 *r,
4058                                       int snum)
4059 {
4060         /* These are the components of the SD we are returning. */
4061
4062         if (info2->secdesc != NULL) {
4063                 /* don't use talloc_steal() here unless you do a deep steal of all
4064                    the SEC_DESC members */
4065
4066                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4067                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4068         }
4069
4070         return WERR_OK;
4071 }
4072
4073 /********************************************************************
4074  * construct_printer_info4
4075  * fill a spoolss_PrinterInfo4 struct
4076  ********************************************************************/
4077
4078 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4079                                       const struct spoolss_PrinterInfo2 *info2,
4080                                       const char *servername,
4081                                       struct spoolss_PrinterInfo4 *r,
4082                                       int snum)
4083 {
4084         WERROR result;
4085
4086         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4087         if (!W_ERROR_IS_OK(result)) {
4088                 return result;
4089         }
4090
4091         if (servername) {
4092                 r->servername   = talloc_strdup(mem_ctx, servername);
4093                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4094         } else {
4095                 r->servername = NULL;
4096         }
4097
4098         r->attributes   = info2->attributes;
4099
4100         return WERR_OK;
4101 }
4102
4103 /********************************************************************
4104  * construct_printer_info5
4105  * fill a spoolss_PrinterInfo5 struct
4106  ********************************************************************/
4107
4108 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4109                                       const struct spoolss_PrinterInfo2 *info2,
4110                                       const char *servername,
4111                                       struct spoolss_PrinterInfo5 *r,
4112                                       int snum)
4113 {
4114         WERROR result;
4115
4116         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4117         if (!W_ERROR_IS_OK(result)) {
4118                 return result;
4119         }
4120
4121         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4122         W_ERROR_HAVE_NO_MEMORY(r->portname);
4123
4124         r->attributes   = info2->attributes;
4125
4126         /* these two are not used by NT+ according to MSDN */
4127         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4128         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4129
4130         return WERR_OK;
4131 }
4132
4133 /********************************************************************
4134  * construct_printer_info_6
4135  * fill a spoolss_PrinterInfo6 struct
4136  ********************************************************************/
4137
4138 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4139                                       struct messaging_context *msg_ctx,
4140                                       const struct spoolss_PrinterInfo2 *info2,
4141                                       const char *servername,
4142                                       struct spoolss_PrinterInfo6 *r,
4143                                       int snum)
4144 {
4145         int count;
4146         print_status_struct status;
4147
4148         count = print_queue_length(msg_ctx, snum, &status);
4149
4150         r->status = nt_printq_status(status.status);
4151
4152         return WERR_OK;
4153 }
4154
4155 /********************************************************************
4156  * construct_printer_info7
4157  * fill a spoolss_PrinterInfo7 struct
4158  ********************************************************************/
4159
4160 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4161                                       struct messaging_context *msg_ctx,
4162                                       const char *servername,
4163                                       struct spoolss_PrinterInfo7 *r,
4164                                       int snum)
4165 {
4166         struct auth_serversupplied_info *session_info;
4167         struct GUID guid;
4168         NTSTATUS status;
4169
4170         status = make_session_info_system(mem_ctx, &session_info);
4171         if (!NT_STATUS_IS_OK(status)) {
4172                 DEBUG(0, ("construct_printer_info7: "
4173                           "Could not create system session_info\n"));
4174                 return WERR_NOMEM;
4175         }
4176
4177         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4178                                  servername,
4179                                  lp_servicename(snum), &guid, NULL)) {
4180                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4181                 r->action = DSPRINT_PUBLISH;
4182         } else {
4183                 r->guid = talloc_strdup(mem_ctx, "");
4184                 r->action = DSPRINT_UNPUBLISH;
4185         }
4186         W_ERROR_HAVE_NO_MEMORY(r->guid);
4187
4188         TALLOC_FREE(session_info);
4189         return WERR_OK;
4190 }
4191
4192 /********************************************************************
4193  * construct_printer_info8
4194  * fill a spoolss_PrinterInfo8 struct
4195  ********************************************************************/
4196
4197 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4198                                       const struct spoolss_PrinterInfo2 *info2,
4199                                       const char *servername,
4200                                       struct spoolss_DeviceModeInfo *r,
4201                                       int snum)
4202 {
4203         WERROR result;
4204         const char *printername;
4205
4206         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4207         if (!W_ERROR_IS_OK(result)) {
4208                 return result;
4209         }
4210
4211         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4212         if (!r->devmode) {
4213                 DEBUG(8,("Returning NULL Devicemode!\n"));
4214         }
4215
4216         compose_devicemode_devicename(r->devmode, printername);
4217
4218         return WERR_OK;
4219 }
4220
4221
4222 /********************************************************************
4223 ********************************************************************/
4224
4225 static bool snum_is_shared_printer(int snum)
4226 {
4227         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4228 }
4229
4230 /********************************************************************
4231  Spoolss_enumprinters.
4232 ********************************************************************/
4233
4234 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4235                                            const struct auth_serversupplied_info *session_info,
4236                                            struct messaging_context *msg_ctx,
4237                                            const char *servername,
4238                                            uint32_t level,
4239                                            uint32_t flags,
4240                                            union spoolss_PrinterInfo **info_p,
4241                                            uint32_t *count_p)
4242 {
4243         int snum;
4244         int n_services = lp_numservices();
4245         union spoolss_PrinterInfo *info = NULL;
4246         uint32_t count = 0;
4247         WERROR result = WERR_OK;
4248
4249         *count_p = 0;
4250         *info_p = NULL;
4251
4252         for (snum = 0; snum < n_services; snum++) {
4253
4254                 const char *printer;
4255                 struct spoolss_PrinterInfo2 *info2;
4256
4257                 if (!snum_is_shared_printer(snum)) {
4258                         continue;
4259                 }
4260
4261                 printer = lp_const_servicename(snum);
4262
4263                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4264                         printer, snum));
4265
4266                 result = winreg_create_printer(mem_ctx,
4267                                                session_info,
4268                                                msg_ctx,
4269                                                printer);
4270                 if (!W_ERROR_IS_OK(result)) {
4271                         goto out;
4272                 }
4273
4274                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4275                                             union spoolss_PrinterInfo,
4276                                             count + 1);
4277                 if (!info) {
4278                         result = WERR_NOMEM;
4279                         goto out;
4280                 }
4281
4282                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4283                                             printer, &info2);
4284                 if (!W_ERROR_IS_OK(result)) {
4285                         goto out;
4286                 }
4287
4288                 switch (level) {
4289                 case 0:
4290                         result = construct_printer_info0(info, session_info,
4291                                                          msg_ctx, info2,
4292                                                          servername,
4293                                                          &info[count].info0, snum);
4294                         break;
4295                 case 1:
4296                         result = construct_printer_info1(info, info2, flags,
4297                                                          servername,
4298                                                          &info[count].info1, snum);
4299                         break;
4300                 case 2:
4301                         result = construct_printer_info2(info, msg_ctx, info2,
4302                                                          servername,
4303                                                          &info[count].info2, snum);
4304                         break;
4305                 case 4:
4306                         result = construct_printer_info4(info, info2,
4307                                                          servername,
4308                                                          &info[count].info4, snum);
4309                         break;
4310                 case 5:
4311                         result = construct_printer_info5(info, info2,
4312                                                          servername,
4313                                                          &info[count].info5, snum);
4314                         break;
4315
4316                 default:
4317                         result = WERR_UNKNOWN_LEVEL;
4318                         goto out;
4319                 }
4320
4321                 if (!W_ERROR_IS_OK(result)) {
4322                         goto out;
4323                 }
4324
4325                 count++;
4326         }
4327
4328         *count_p = count;
4329         *info_p = info;
4330
4331  out:
4332         if (!W_ERROR_IS_OK(result)) {
4333                 TALLOC_FREE(info);
4334                 return result;
4335         }
4336
4337         *info_p = info;
4338
4339         return WERR_OK;
4340 }
4341
4342 /********************************************************************
4343  * handle enumeration of printers at level 0
4344  ********************************************************************/
4345
4346 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4347                                   const struct auth_serversupplied_info *session_info,
4348                                   struct messaging_context *msg_ctx,
4349                                   uint32_t flags,
4350                                   const char *servername,
4351                                   union spoolss_PrinterInfo **info,
4352                                   uint32_t *count)
4353 {
4354         DEBUG(4,("enum_all_printers_info_0\n"));
4355
4356         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4357                                             servername, 0, flags, info, count);
4358 }
4359
4360
4361 /********************************************************************
4362 ********************************************************************/
4363
4364 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4365                                        const struct auth_serversupplied_info *session_info,
4366                                        struct messaging_context *msg_ctx,
4367                                        const char *servername,
4368                                        uint32_t flags,
4369                                        union spoolss_PrinterInfo **info,
4370                                        uint32_t *count)
4371 {
4372         DEBUG(4,("enum_all_printers_info_1\n"));
4373
4374         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4375                                             servername, 1, flags, info, count);
4376 }
4377
4378 /********************************************************************
4379  enum_all_printers_info_1_local.
4380 *********************************************************************/
4381
4382 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4383                                              const struct auth_serversupplied_info *session_info,
4384                                              struct messaging_context *msg_ctx,
4385                                              const char *servername,
4386                                              union spoolss_PrinterInfo **info,
4387                                              uint32_t *count)
4388 {
4389         DEBUG(4,("enum_all_printers_info_1_local\n"));
4390
4391         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4392                                         servername, PRINTER_ENUM_ICON8, info, count);
4393 }
4394
4395 /********************************************************************
4396  enum_all_printers_info_1_name.
4397 *********************************************************************/
4398
4399 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4400                                             const struct auth_serversupplied_info *session_info,
4401                                             struct messaging_context *msg_ctx,
4402                                             const char *servername,
4403                                             union spoolss_PrinterInfo **info,
4404                                             uint32_t *count)
4405 {
4406         const char *s = servername;
4407
4408         DEBUG(4,("enum_all_printers_info_1_name\n"));
4409
4410         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4411                 s = servername + 2;
4412         }
4413
4414         if (!is_myname_or_ipaddr(s)) {
4415                 return WERR_INVALID_NAME;
4416         }
4417
4418         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4419                                         servername, PRINTER_ENUM_ICON8, info, count);
4420 }
4421
4422 /********************************************************************
4423  enum_all_printers_info_1_network.
4424 *********************************************************************/
4425
4426 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4427                                                const struct auth_serversupplied_info *session_info,
4428                                                struct messaging_context *msg_ctx,
4429                                                const char *servername,
4430                                                union spoolss_PrinterInfo **info,
4431                                                uint32_t *count)
4432 {
4433         const char *s = servername;
4434
4435         DEBUG(4,("enum_all_printers_info_1_network\n"));
4436
4437         /* If we respond to a enum_printers level 1 on our name with flags
4438            set to PRINTER_ENUM_REMOTE with a list of printers then these
4439            printers incorrectly appear in the APW browse list.
4440            Specifically the printers for the server appear at the workgroup
4441            level where all the other servers in the domain are
4442            listed. Windows responds to this call with a
4443            WERR_CAN_NOT_COMPLETE so we should do the same. */
4444
4445         if (servername[0] == '\\' && servername[1] == '\\') {
4446                  s = servername + 2;
4447         }
4448
4449         if (is_myname_or_ipaddr(s)) {
4450                  return WERR_CAN_NOT_COMPLETE;
4451         }
4452
4453         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4454                                         servername, PRINTER_ENUM_NAME, info, count);
4455 }
4456
4457 /********************************************************************
4458  * api_spoolss_enumprinters
4459  *
4460  * called from api_spoolss_enumprinters (see this to understand)
4461  ********************************************************************/
4462
4463 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4464                                        const struct auth_serversupplied_info *session_info,
4465                                        struct messaging_context *msg_ctx,
4466                                        const char *servername,
4467                                        union spoolss_PrinterInfo **info,
4468                                        uint32_t *count)
4469 {
4470         DEBUG(4,("enum_all_printers_info_2\n"));
4471
4472         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4473                                             servername, 2, 0, info, count);
4474 }
4475
4476 /********************************************************************
4477  * handle enumeration of printers at level 1
4478  ********************************************************************/
4479
4480 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4481                                   const struct auth_serversupplied_info *session_info,
4482                                   struct messaging_context *msg_ctx,
4483                                   uint32_t flags,
4484                                   const char *servername,
4485                                   union spoolss_PrinterInfo **info,
4486                                   uint32_t *count)
4487 {
4488         /* Not all the flags are equals */
4489
4490         if (flags & PRINTER_ENUM_LOCAL) {
4491                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4492                                                       msg_ctx, servername, info, count);
4493         }
4494
4495         if (flags & PRINTER_ENUM_NAME) {
4496                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4497                                                      msg_ctx, servername, info,
4498                                                      count);
4499         }
4500
4501         if (flags & PRINTER_ENUM_NETWORK) {
4502                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4503                                                         msg_ctx, servername, info,
4504                                                         count);
4505         }
4506
4507         return WERR_OK; /* NT4sp5 does that */
4508 }
4509
4510 /********************************************************************
4511  * handle enumeration of printers at level 2
4512  ********************************************************************/
4513
4514 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4515                                   const struct auth_serversupplied_info *session_info,
4516                                   struct messaging_context *msg_ctx,
4517                                   uint32_t flags,
4518                                   const char *servername,
4519                                   union spoolss_PrinterInfo **info,
4520                                   uint32_t *count)
4521 {
4522         if (flags & PRINTER_ENUM_LOCAL) {
4523
4524                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4525                                                 servername,
4526                                                 info, count);
4527         }
4528
4529         if (flags & PRINTER_ENUM_NAME) {
4530                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4531                         return WERR_INVALID_NAME;
4532                 }
4533
4534                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4535                                                 servername,
4536                                                 info, count);
4537         }
4538
4539         if (flags & PRINTER_ENUM_REMOTE) {
4540                 return WERR_UNKNOWN_LEVEL;
4541         }
4542
4543         return WERR_OK;
4544 }
4545
4546 /********************************************************************
4547  * handle enumeration of printers at level 4
4548  ********************************************************************/
4549
4550 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4551                                   const struct auth_serversupplied_info *session_info,
4552                                   struct messaging_context *msg_ctx,
4553                                   uint32_t flags,
4554                                   const char *servername,
4555                                   union spoolss_PrinterInfo **info,
4556                                   uint32_t *count)
4557 {
4558         DEBUG(4,("enum_all_printers_info_4\n"));
4559
4560         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4561                                             servername, 4, flags, info, count);
4562 }
4563
4564
4565 /********************************************************************
4566  * handle enumeration of printers at level 5
4567  ********************************************************************/
4568
4569 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4570                                   const struct auth_serversupplied_info *session_info,
4571                                   struct messaging_context *msg_ctx,
4572                                   uint32_t flags,
4573                                   const char *servername,
4574                                   union spoolss_PrinterInfo **info,
4575                                   uint32_t *count)
4576 {
4577         DEBUG(4,("enum_all_printers_info_5\n"));
4578
4579         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4580                                             servername, 5, flags, info, count);
4581 }
4582
4583 /****************************************************************
4584  _spoolss_EnumPrinters
4585 ****************************************************************/
4586
4587 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4588                              struct spoolss_EnumPrinters *r)
4589 {
4590         const struct auth_serversupplied_info *session_info = get_session_info_system();
4591         WERROR result;
4592
4593         /* that's an [in out] buffer */
4594
4595         if (!r->in.buffer && (r->in.offered != 0)) {
4596                 return WERR_INVALID_PARAM;
4597         }
4598
4599         DEBUG(4,("_spoolss_EnumPrinters\n"));
4600
4601         *r->out.needed = 0;
4602         *r->out.count = 0;
4603         *r->out.info = NULL;
4604
4605         /*
4606          * Level 1:
4607          *          flags==PRINTER_ENUM_NAME
4608          *           if name=="" then enumerates all printers
4609          *           if name!="" then enumerate the printer
4610          *          flags==PRINTER_ENUM_REMOTE
4611          *          name is NULL, enumerate printers
4612          * Level 2: name!="" enumerates printers, name can't be NULL
4613          * Level 3: doesn't exist
4614          * Level 4: does a local registry lookup
4615          * Level 5: same as Level 2
4616          */
4617
4618         if (r->in.server && r->in.server[0] == '\0') {
4619                 r->in.server = NULL;
4620         }
4621
4622         switch (r->in.level) {
4623         case 0:
4624                 result = enumprinters_level0(p->mem_ctx, session_info,
4625                                              p->msg_ctx, r->in.flags,
4626                                              r->in.server,
4627                                              r->out.info, r->out.count);
4628                 break;
4629         case 1:
4630                 result = enumprinters_level1(p->mem_ctx, session_info,
4631                                              p->msg_ctx, r->in.flags,
4632                                              r->in.server,
4633                                              r->out.info, r->out.count);
4634                 break;
4635         case 2:
4636                 result = enumprinters_level2(p->mem_ctx, session_info,
4637                                              p->msg_ctx, r->in.flags,
4638                                              r->in.server,
4639                                              r->out.info, r->out.count);
4640                 break;
4641         case 4:
4642                 result = enumprinters_level4(p->mem_ctx, session_info,
4643                                              p->msg_ctx, r->in.flags,
4644                                              r->in.server,
4645                                              r->out.info, r->out.count);
4646                 break;
4647         case 5:
4648                 result = enumprinters_level5(p->mem_ctx, session_info,
4649                                              p->msg_ctx, r->in.flags,
4650                                              r->in.server,
4651                                              r->out.info, r->out.count);
4652                 break;
4653         default:
4654                 return WERR_UNKNOWN_LEVEL;
4655         }
4656
4657         if (!W_ERROR_IS_OK(result)) {
4658                 return result;
4659         }
4660
4661         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4662                                                      spoolss_EnumPrinters,
4663                                                      *r->out.info, r->in.level,
4664                                                      *r->out.count);
4665         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4666         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4667
4668         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4669 }
4670
4671 /****************************************************************
4672  _spoolss_GetPrinter
4673 ****************************************************************/
4674
4675 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4676                            struct spoolss_GetPrinter *r)
4677 {
4678         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4679         struct spoolss_PrinterInfo2 *info2 = NULL;
4680         WERROR result = WERR_OK;
4681         int snum;
4682
4683         /* that's an [in out] buffer */
4684
4685         if (!r->in.buffer && (r->in.offered != 0)) {
4686                 return WERR_INVALID_PARAM;
4687         }
4688
4689         *r->out.needed = 0;
4690
4691         if (Printer == NULL) {
4692                 return WERR_BADFID;
4693         }
4694
4695         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4696                 return WERR_BADFID;
4697         }
4698
4699         result = winreg_get_printer(p->mem_ctx,
4700                                     get_session_info_system(),
4701                                     p->msg_ctx,
4702                                     lp_const_servicename(snum),
4703                                     &info2);
4704         if (!W_ERROR_IS_OK(result)) {
4705                 goto out;
4706         }
4707
4708         switch (r->in.level) {
4709         case 0:
4710                 result = construct_printer_info0(p->mem_ctx,
4711                                                  get_session_info_system(),
4712                                                  p->msg_ctx,
4713                                                  info2,
4714                                                  Printer->servername,
4715                                                  &r->out.info->info0,
4716                                                  snum);
4717                 break;
4718         case 1:
4719                 result = construct_printer_info1(p->mem_ctx, info2,
4720                                                  PRINTER_ENUM_ICON8,
4721                                                  Printer->servername,
4722                                                  &r->out.info->info1, snum);
4723                 break;
4724         case 2:
4725                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4726                                                  Printer->servername,
4727                                                  &r->out.info->info2, snum);
4728                 break;
4729         case 3:
4730                 result = construct_printer_info3(p->mem_ctx, info2,
4731                                                  Printer->servername,
4732                                                  &r->out.info->info3, snum);
4733                 break;
4734         case 4:
4735                 result = construct_printer_info4(p->mem_ctx, info2,
4736                                                  Printer->servername,
4737                                                  &r->out.info->info4, snum);
4738                 break;
4739         case 5:
4740                 result = construct_printer_info5(p->mem_ctx, info2,
4741                                                  Printer->servername,
4742                                                  &r->out.info->info5, snum);
4743                 break;
4744         case 6:
4745                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info6, snum);
4748                 break;
4749         case 7:
4750                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info7, snum);
4753                 break;
4754         case 8:
4755                 result = construct_printer_info8(p->mem_ctx, info2,
4756                                                  Printer->servername,
4757                                                  &r->out.info->info8, snum);
4758                 break;
4759         default:
4760                 result = WERR_UNKNOWN_LEVEL;
4761                 break;
4762         }
4763
4764  out:
4765         if (!W_ERROR_IS_OK(result)) {
4766                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4767                           r->in.level, win_errstr(result)));
4768                 TALLOC_FREE(r->out.info);
4769                 return result;
4770         }
4771
4772         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4773                                                r->out.info, r->in.level);
4774         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4775
4776         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4777 }
4778
4779 /********************************************************************
4780  ********************************************************************/
4781
4782 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4783         do { \
4784                 if (in && strlen(in)) { \
4785                         out = talloc_strdup(mem_ctx, in); \
4786                 } else { \
4787                         out = talloc_strdup(mem_ctx, ""); \
4788                 } \
4789                 W_ERROR_HAVE_NO_MEMORY(out); \
4790         } while (0);
4791
4792 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4793         do { \
4794                 if (in && strlen(in)) { \
4795                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4796                 } else { \
4797                         out = talloc_strdup(mem_ctx, ""); \
4798                 } \
4799                 W_ERROR_HAVE_NO_MEMORY(out); \
4800         } while (0);
4801
4802 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4803                                                   const char **string_array,
4804                                                   const char ***presult,
4805                                                   const char *cservername,
4806                                                   const char *arch,
4807                                                   int version)
4808 {
4809         int i, num_strings = 0;
4810         const char **array = NULL;
4811
4812         if (string_array == NULL) {
4813                 return WERR_INVALID_PARAMETER;
4814         }
4815
4816         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4817                 const char *str = NULL;
4818
4819                 if (cservername == NULL || arch == NULL) {
4820                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4821                 } else {
4822                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4823                 }
4824
4825                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4826                         TALLOC_FREE(array);
4827                         return WERR_NOMEM;
4828                 }
4829         }
4830
4831         if (i > 0) {
4832                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4833                              &array, &num_strings);
4834         }
4835
4836         if (presult) {
4837                 *presult = array;
4838         }
4839
4840         return WERR_OK;
4841 }
4842
4843 /********************************************************************
4844  * fill a spoolss_DriverInfo1 struct
4845  ********************************************************************/
4846
4847 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4848                                         struct spoolss_DriverInfo1 *r,
4849                                         const struct spoolss_DriverInfo8 *driver,
4850                                         const char *servername)
4851 {
4852         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4853         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4854
4855         return WERR_OK;
4856 }
4857
4858 /********************************************************************
4859  * fill a spoolss_DriverInfo2 struct
4860  ********************************************************************/
4861
4862 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4863                                         struct spoolss_DriverInfo2 *r,
4864                                         const struct spoolss_DriverInfo8 *driver,
4865                                         const char *servername)
4866
4867 {
4868         const char *cservername = canon_servername(servername);
4869
4870         r->version              = driver->version;
4871
4872         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4873         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4874         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4875         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4876
4877         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4878                                driver->architecture,
4879                                driver->version,
4880                                driver->driver_path,
4881                                r->driver_path);
4882
4883         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4884                                driver->architecture,
4885                                driver->version,
4886                                driver->data_file,
4887                                r->data_file);
4888
4889         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4890                                driver->architecture,
4891                                driver->version,
4892                                driver->config_file,
4893                                r->config_file);
4894
4895         return WERR_OK;
4896 }
4897
4898 /********************************************************************
4899  * fill a spoolss_DriverInfo3 struct
4900  ********************************************************************/
4901
4902 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4903                                         struct spoolss_DriverInfo3 *r,
4904                                         const struct spoolss_DriverInfo8 *driver,
4905                                         const char *servername)
4906 {
4907         const char *cservername = canon_servername(servername);
4908
4909         r->version              = driver->version;
4910
4911         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4912         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4913         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4914         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4915
4916         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4917                                driver->architecture,
4918                                driver->version,
4919                                driver->driver_path,
4920                                r->driver_path);
4921
4922         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923                                driver->architecture,
4924                                driver->version,
4925                                driver->data_file,
4926                                r->data_file);
4927
4928         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4929                                driver->architecture,
4930                                driver->version,
4931                                driver->config_file,
4932                                r->config_file);
4933
4934         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4935                                driver->architecture,
4936                                driver->version,
4937                                driver->help_file,
4938                                r->help_file);
4939
4940         FILL_DRIVER_STRING(mem_ctx,
4941                            driver->monitor_name,
4942                            r->monitor_name);
4943
4944         FILL_DRIVER_STRING(mem_ctx,
4945                            driver->default_datatype,
4946                            r->default_datatype);
4947
4948         return string_array_from_driver_info(mem_ctx,
4949                                              driver->dependent_files,
4950                                              &r->dependent_files,
4951                                              cservername,
4952                                              driver->architecture,
4953                                              driver->version);
4954 }
4955
4956 /********************************************************************
4957  * fill a spoolss_DriverInfo4 struct
4958  ********************************************************************/
4959
4960 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4961                                         struct spoolss_DriverInfo4 *r,
4962                                         const struct spoolss_DriverInfo8 *driver,
4963                                         const char *servername)
4964 {
4965         const char *cservername = canon_servername(servername);
4966         WERROR result;
4967
4968         r->version              = driver->version;
4969
4970         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4971         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4972         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4973         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4974
4975         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4976                                driver->architecture,
4977                                driver->version,
4978                                driver->driver_path,
4979                                r->driver_path);
4980
4981         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982                                driver->architecture,
4983                                driver->version,
4984                                driver->data_file,
4985                                r->data_file);
4986
4987         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4988                                driver->architecture,
4989                                driver->version,
4990                                driver->config_file,
4991                                r->config_file);
4992
4993         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994                                driver->architecture,
4995                                driver->version,
4996                                driver->help_file,
4997                                r->help_file);
4998
4999         result = string_array_from_driver_info(mem_ctx,
5000                                                driver->dependent_files,
5001                                                &r->dependent_files,
5002                                                cservername,
5003                                                driver->architecture,
5004                                                driver->version);
5005         if (!W_ERROR_IS_OK(result)) {
5006                 return result;
5007         }
5008
5009         FILL_DRIVER_STRING(mem_ctx,
5010                            driver->monitor_name,
5011                            r->monitor_name);
5012
5013         FILL_DRIVER_STRING(mem_ctx,
5014                            driver->default_datatype,
5015                            r->default_datatype);
5016
5017
5018         result = string_array_from_driver_info(mem_ctx,
5019                                                driver->previous_names,
5020                                                &r->previous_names,
5021                                                NULL, NULL, 0);
5022
5023         return result;
5024 }
5025
5026 /********************************************************************
5027  * fill a spoolss_DriverInfo5 struct
5028  ********************************************************************/
5029
5030 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5031                                         struct spoolss_DriverInfo5 *r,
5032                                         const struct spoolss_DriverInfo8 *driver,
5033                                         const char *servername)
5034 {
5035         const char *cservername = canon_servername(servername);
5036
5037         r->version              = driver->version;
5038
5039         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5040         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5041         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5042         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5043
5044         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5045                                driver->architecture,
5046                                driver->version,
5047                                driver->driver_path,
5048                                r->driver_path);
5049
5050         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051                                driver->architecture,
5052                                driver->version,
5053                                driver->data_file,
5054                                r->data_file);
5055
5056         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057                                driver->architecture,
5058                                driver->version,
5059                                driver->config_file,
5060                                r->config_file);
5061
5062         r->driver_attributes    = 0;
5063         r->config_version       = 0;
5064         r->driver_version       = 0;
5065
5066         return WERR_OK;
5067 }
5068 /********************************************************************
5069  * fill a spoolss_DriverInfo6 struct
5070  ********************************************************************/
5071
5072 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5073                                         struct spoolss_DriverInfo6 *r,
5074                                         const struct spoolss_DriverInfo8 *driver,
5075                                         const char *servername)
5076 {
5077         const char *cservername = canon_servername(servername);
5078         WERROR result;
5079
5080         r->version              = driver->version;
5081
5082         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5083         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5084         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5085         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5086
5087         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5088                                driver->architecture,
5089                                driver->version,
5090                                driver->driver_path,
5091                                r->driver_path);
5092
5093         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094                                driver->architecture,
5095                                driver->version,
5096                                driver->data_file,
5097                                r->data_file);
5098
5099         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5100                                driver->architecture,
5101                                driver->version,
5102                                driver->config_file,
5103                                r->config_file);
5104
5105         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5106                                driver->architecture,
5107                                driver->version,
5108                                driver->help_file,
5109                                r->help_file);
5110
5111         FILL_DRIVER_STRING(mem_ctx,
5112                            driver->monitor_name,
5113                            r->monitor_name);
5114
5115         FILL_DRIVER_STRING(mem_ctx,
5116                            driver->default_datatype,
5117                            r->default_datatype);
5118
5119         result = string_array_from_driver_info(mem_ctx,
5120                                                driver->dependent_files,
5121                                                &r->dependent_files,
5122                                                cservername,
5123                                                driver->architecture,
5124                                                driver->version);
5125         if (!W_ERROR_IS_OK(result)) {
5126                 return result;
5127         }
5128
5129         result = string_array_from_driver_info(mem_ctx,
5130                                                driver->previous_names,
5131                                                &r->previous_names,
5132                                                NULL, NULL, 0);
5133         if (!W_ERROR_IS_OK(result)) {
5134                 return result;
5135         }
5136
5137         r->driver_date          = driver->driver_date;
5138         r->driver_version       = driver->driver_version;
5139
5140         FILL_DRIVER_STRING(mem_ctx,
5141                            driver->manufacturer_name,
5142                            r->manufacturer_name);
5143         FILL_DRIVER_STRING(mem_ctx,
5144                            driver->manufacturer_url,
5145                            r->manufacturer_url);
5146         FILL_DRIVER_STRING(mem_ctx,
5147                            driver->hardware_id,
5148                            r->hardware_id);
5149         FILL_DRIVER_STRING(mem_ctx,
5150                            driver->provider,
5151                            r->provider);
5152
5153         return WERR_OK;
5154 }
5155
5156 /********************************************************************
5157  * fill a spoolss_DriverInfo8 struct
5158  ********************************************************************/
5159
5160 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5161                                         struct spoolss_DriverInfo8 *r,
5162                                         const struct spoolss_DriverInfo8 *driver,
5163                                         const char *servername)
5164 {
5165         const char *cservername = canon_servername(servername);
5166         WERROR result;
5167
5168         r->version              = driver->version;
5169
5170         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5171         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5172         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5173         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5174
5175         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5176                                driver->architecture,
5177                                driver->version,
5178                                driver->driver_path,
5179                                r->driver_path);
5180
5181         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182                                driver->architecture,
5183                                driver->version,
5184                                driver->data_file,
5185                                r->data_file);
5186
5187         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5188                                driver->architecture,
5189                                driver->version,
5190                                driver->config_file,
5191                                r->config_file);
5192
5193         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194                                driver->architecture,
5195                                driver->version,
5196                                driver->help_file,
5197                                r->help_file);
5198
5199         FILL_DRIVER_STRING(mem_ctx,
5200                            driver->monitor_name,
5201                            r->monitor_name);
5202
5203         FILL_DRIVER_STRING(mem_ctx,
5204                            driver->default_datatype,
5205                            r->default_datatype);
5206
5207         result = string_array_from_driver_info(mem_ctx,
5208                                                driver->dependent_files,
5209                                                &r->dependent_files,
5210                                                cservername,
5211                                                driver->architecture,
5212                                                driver->version);
5213         if (!W_ERROR_IS_OK(result)) {
5214                 return result;
5215         }
5216
5217         result = string_array_from_driver_info(mem_ctx,
5218                                                driver->previous_names,
5219                                                &r->previous_names,
5220                                                NULL, NULL, 0);
5221         if (!W_ERROR_IS_OK(result)) {
5222                 return result;
5223         }
5224
5225         r->driver_date          = driver->driver_date;
5226         r->driver_version       = driver->driver_version;
5227
5228         FILL_DRIVER_STRING(mem_ctx,
5229                            driver->manufacturer_name,
5230                            r->manufacturer_name);
5231         FILL_DRIVER_STRING(mem_ctx,
5232                            driver->manufacturer_url,
5233                            r->manufacturer_url);
5234         FILL_DRIVER_STRING(mem_ctx,
5235                            driver->hardware_id,
5236                            r->hardware_id);
5237         FILL_DRIVER_STRING(mem_ctx,
5238                            driver->provider,
5239                            r->provider);
5240
5241         FILL_DRIVER_STRING(mem_ctx,
5242                            driver->print_processor,
5243                            r->print_processor);
5244         FILL_DRIVER_STRING(mem_ctx,
5245                            driver->vendor_setup,
5246                            r->vendor_setup);
5247
5248         result = string_array_from_driver_info(mem_ctx,
5249                                                driver->color_profiles,
5250                                                &r->color_profiles,
5251                                                NULL, NULL, 0);
5252         if (!W_ERROR_IS_OK(result)) {
5253                 return result;
5254         }
5255
5256         FILL_DRIVER_STRING(mem_ctx,
5257                            driver->inf_path,
5258                            r->inf_path);
5259
5260         r->printer_driver_attributes    = driver->printer_driver_attributes;
5261
5262         result = string_array_from_driver_info(mem_ctx,
5263                                                driver->core_driver_dependencies,
5264                                                &r->core_driver_dependencies,
5265                                                NULL, NULL, 0);
5266         if (!W_ERROR_IS_OK(result)) {
5267                 return result;
5268         }
5269
5270         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5271         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5272
5273         return WERR_OK;
5274 }
5275
5276 #if 0 /* disabled until marshalling issues are resolved - gd */
5277 /********************************************************************
5278  ********************************************************************/
5279
5280 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5281                                           struct spoolss_DriverFileInfo *r,
5282                                           const char *cservername,
5283                                           const char *file_name,
5284                                           enum spoolss_DriverFileType file_type,
5285                                           uint32_t file_version)
5286 {
5287         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5288                                           cservername, file_name);
5289         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5290         r->file_type    = file_type;
5291         r->file_version = file_version;
5292
5293         return WERR_OK;
5294 }
5295
5296 /********************************************************************
5297  ********************************************************************/
5298
5299 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5300                                                  const struct spoolss_DriverInfo8 *driver,
5301                                                  const char *cservername,
5302                                                  struct spoolss_DriverFileInfo **info_p,
5303                                                  uint32_t *count_p)
5304 {
5305         struct spoolss_DriverFileInfo *info = NULL;
5306         uint32_t count = 0;
5307         WERROR result;
5308         uint32_t i;
5309
5310         *info_p = NULL;
5311         *count_p = 0;
5312
5313         if (strlen(driver->driver_path)) {
5314                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5315                                             struct spoolss_DriverFileInfo,
5316                                             count + 1);
5317                 W_ERROR_HAVE_NO_MEMORY(info);
5318                 result = fill_spoolss_DriverFileInfo(info,
5319                                                      &info[count],
5320                                                      cservername,
5321                                                      driver->driver_path,
5322                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5323                                                      0);
5324                 W_ERROR_NOT_OK_RETURN(result);
5325                 count++;
5326         }
5327
5328         if (strlen(driver->config_file)) {
5329                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5330                                             struct spoolss_DriverFileInfo,
5331                                             count + 1);
5332                 W_ERROR_HAVE_NO_MEMORY(info);
5333                 result = fill_spoolss_DriverFileInfo(info,
5334                                                      &info[count],
5335                                                      cservername,
5336                                                      driver->config_file,
5337                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5338                                                      0);
5339                 W_ERROR_NOT_OK_RETURN(result);
5340                 count++;
5341         }
5342
5343         if (strlen(driver->data_file)) {
5344                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5345                                             struct spoolss_DriverFileInfo,
5346                                             count + 1);
5347                 W_ERROR_HAVE_NO_MEMORY(info);
5348                 result = fill_spoolss_DriverFileInfo(info,
5349                                                      &info[count],
5350                                                      cservername,
5351                                                      driver->data_file,
5352                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5353                                                      0);
5354                 W_ERROR_NOT_OK_RETURN(result);
5355                 count++;
5356         }
5357
5358         if (strlen(driver->help_file)) {
5359                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5360                                             struct spoolss_DriverFileInfo,
5361                                             count + 1);
5362                 W_ERROR_HAVE_NO_MEMORY(info);
5363                 result = fill_spoolss_DriverFileInfo(info,
5364                                                      &info[count],
5365                                                      cservername,
5366                                                      driver->help_file,
5367                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5368                                                      0);
5369                 W_ERROR_NOT_OK_RETURN(result);
5370                 count++;
5371         }
5372
5373         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5374                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5375                                             struct spoolss_DriverFileInfo,
5376                                             count + 1);
5377                 W_ERROR_HAVE_NO_MEMORY(info);
5378                 result = fill_spoolss_DriverFileInfo(info,
5379                                                      &info[count],
5380                                                      cservername,
5381                                                      driver->dependent_files[i],
5382                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5383                                                      0);
5384                 W_ERROR_NOT_OK_RETURN(result);
5385                 count++;
5386         }
5387
5388         *info_p = info;
5389         *count_p = count;
5390
5391         return WERR_OK;
5392 }
5393
5394 /********************************************************************
5395  * fill a spoolss_DriverInfo101 struct
5396  ********************************************************************/
5397
5398 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5399                                           struct spoolss_DriverInfo101 *r,
5400                                           const struct spoolss_DriverInfo8 *driver,
5401                                           const char *servername)
5402 {
5403         const char *cservername = canon_servername(servername);
5404         WERROR result;
5405
5406         r->version              = driver->version;
5407
5408         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5409         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5410         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5411         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5412
5413         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5414                                                     cservername,
5415                                                     &r->file_info,
5416                                                     &r->file_count);
5417         if (!W_ERROR_IS_OK(result)) {
5418                 return result;
5419         }
5420
5421         FILL_DRIVER_STRING(mem_ctx,
5422                            driver->monitor_name,
5423                            r->monitor_name);
5424
5425         FILL_DRIVER_STRING(mem_ctx,
5426                            driver->default_datatype,
5427                            r->default_datatype);
5428
5429         result = string_array_from_driver_info(mem_ctx,
5430                                                driver->previous_names,
5431                                                &r->previous_names,
5432                                                NULL, NULL, 0);
5433         if (!W_ERROR_IS_OK(result)) {
5434                 return result;
5435         }
5436
5437         r->driver_date          = driver->driver_date;
5438         r->driver_version       = driver->driver_version;
5439
5440         FILL_DRIVER_STRING(mem_ctx,
5441                            driver->manufacturer_name,
5442                            r->manufacturer_name);
5443         FILL_DRIVER_STRING(mem_ctx,
5444                            driver->manufacturer_url,
5445                            r->manufacturer_url);
5446         FILL_DRIVER_STRING(mem_ctx,
5447                            driver->hardware_id,
5448                            r->hardware_id);
5449         FILL_DRIVER_STRING(mem_ctx,
5450                            driver->provider,
5451                            r->provider);
5452
5453         return WERR_OK;
5454 }
5455 #endif
5456 /********************************************************************
5457  ********************************************************************/
5458
5459 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5460                                                   const struct auth_serversupplied_info *session_info,
5461                                                   struct messaging_context *msg_ctx,
5462                                                   uint32_t level,
5463                                                   union spoolss_DriverInfo *r,
5464                                                   int snum,
5465                                                   const char *servername,
5466                                                   const char *architecture,
5467                                                   uint32_t version)
5468 {
5469         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5470         struct spoolss_DriverInfo8 *driver;
5471         WERROR result;
5472
5473         if (level == 101) {
5474                 return WERR_UNKNOWN_LEVEL;
5475         }
5476
5477         result = winreg_get_printer(mem_ctx,
5478                                     session_info,
5479                                     msg_ctx,
5480                                     lp_const_servicename(snum),
5481                                     &pinfo2);
5482
5483         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5484                 win_errstr(result)));
5485
5486         if (!W_ERROR_IS_OK(result)) {
5487                 return WERR_INVALID_PRINTER_NAME;
5488         }
5489
5490         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5491                                    architecture,
5492                                    pinfo2->drivername, version, &driver);
5493
5494         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5495                 win_errstr(result)));
5496
5497         if (!W_ERROR_IS_OK(result)) {
5498                 /*
5499                  * Is this a W2k client ?
5500                  */
5501
5502                 if (version < 3) {
5503                         talloc_free(pinfo2);
5504                         return WERR_UNKNOWN_PRINTER_DRIVER;
5505                 }
5506
5507                 /* Yes - try again with a WinNT driver. */
5508                 version = 2;
5509                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5510                                            architecture,
5511                                            pinfo2->drivername,
5512                                            version, &driver);
5513                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5514                         win_errstr(result)));
5515                 if (!W_ERROR_IS_OK(result)) {
5516                         talloc_free(pinfo2);
5517                         return WERR_UNKNOWN_PRINTER_DRIVER;
5518                 }
5519         }
5520
5521         switch (level) {
5522         case 1:
5523                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5524                 break;
5525         case 2:
5526                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5527                 break;
5528         case 3:
5529                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5530                 break;
5531         case 4:
5532                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5533                 break;
5534         case 5:
5535                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5536                 break;
5537         case 6:
5538                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5539                 break;
5540         case 8:
5541                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5542                 break;
5543 #if 0 /* disabled until marshalling issues are resolved - gd */
5544         case 101:
5545                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5546                 break;
5547 #endif
5548         default:
5549                 result = WERR_UNKNOWN_LEVEL;
5550                 break;
5551         }
5552
5553         talloc_free(pinfo2);
5554         talloc_free(driver);
5555
5556         return result;
5557 }
5558
5559 /****************************************************************
5560  _spoolss_GetPrinterDriver2
5561 ****************************************************************/
5562
5563 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5564                                   struct spoolss_GetPrinterDriver2 *r)
5565 {
5566         struct printer_handle *printer;
5567         WERROR result;
5568
5569         int snum;
5570
5571         /* that's an [in out] buffer */
5572
5573         if (!r->in.buffer && (r->in.offered != 0)) {
5574                 return WERR_INVALID_PARAM;
5575         }
5576
5577         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5578
5579         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5580                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5581                 return WERR_INVALID_PRINTER_NAME;
5582         }
5583
5584         *r->out.needed = 0;
5585         *r->out.server_major_version = 0;
5586         *r->out.server_minor_version = 0;
5587
5588         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5589                 return WERR_BADFID;
5590         }
5591
5592         result = construct_printer_driver_info_level(p->mem_ctx,
5593                                                      get_session_info_system(),
5594                                                      p->msg_ctx,
5595                                                      r->in.level, r->out.info,
5596                                                      snum, printer->servername,
5597                                                      r->in.architecture,
5598                                                      r->in.client_major_version);
5599         if (!W_ERROR_IS_OK(result)) {
5600                 TALLOC_FREE(r->out.info);
5601                 return result;
5602         }
5603
5604         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5605                                                r->out.info, r->in.level);
5606         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5607
5608         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5609 }
5610
5611
5612 /****************************************************************
5613  _spoolss_StartPagePrinter
5614 ****************************************************************/
5615
5616 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5617                                  struct spoolss_StartPagePrinter *r)
5618 {
5619         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5620
5621         if (!Printer) {
5622                 DEBUG(3,("_spoolss_StartPagePrinter: "
5623                         "Error in startpageprinter printer handle\n"));
5624                 return WERR_BADFID;
5625         }
5626
5627         Printer->page_started = true;
5628         return WERR_OK;
5629 }
5630
5631 /****************************************************************
5632  _spoolss_EndPagePrinter
5633 ****************************************************************/
5634
5635 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5636                                struct spoolss_EndPagePrinter *r)
5637 {
5638         int snum;
5639
5640         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5641
5642         if (!Printer) {
5643                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5644                         OUR_HANDLE(r->in.handle)));
5645                 return WERR_BADFID;
5646         }
5647
5648         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5649                 return WERR_BADFID;
5650
5651         Printer->page_started = false;
5652         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5653
5654         return WERR_OK;
5655 }
5656
5657 /****************************************************************
5658  _spoolss_StartDocPrinter
5659 ****************************************************************/
5660
5661 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5662                                 struct spoolss_StartDocPrinter *r)
5663 {
5664         struct spoolss_DocumentInfo1 *info_1;
5665         int snum;
5666         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5667         WERROR werr;
5668
5669         if (!Printer) {
5670                 DEBUG(2,("_spoolss_StartDocPrinter: "
5671                         "Invalid handle (%s:%u:%u)\n",
5672                         OUR_HANDLE(r->in.handle)));
5673                 return WERR_BADFID;
5674         }
5675
5676         if (Printer->jobid) {
5677                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5678                           "StartDocPrinter called twice! "
5679                           "(existing jobid = %d)\n", Printer->jobid));
5680                 return WERR_INVALID_HANDLE;
5681         }
5682
5683         if (r->in.level != 1) {
5684                 return WERR_UNKNOWN_LEVEL;
5685         }
5686
5687         info_1 = r->in.info.info1;
5688
5689         /*
5690          * a nice thing with NT is it doesn't listen to what you tell it.
5691          * when asked to send _only_ RAW datas, it tries to send datas
5692          * in EMF format.
5693          *
5694          * So I add checks like in NT Server ...
5695          */
5696
5697         if (info_1->datatype) {
5698                 if (strcmp(info_1->datatype, "RAW") != 0) {
5699                         *r->out.job_id = 0;
5700                         return WERR_INVALID_DATATYPE;
5701                 }
5702         }
5703
5704         /* get the share number of the printer */
5705         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5706                 return WERR_BADFID;
5707         }
5708
5709         werr = print_job_start(p->session_info,
5710                                p->msg_ctx,
5711                                p->client_id->name,
5712                                snum,
5713                                info_1->document_name,
5714                                info_1->output_file,
5715                                Printer->devmode,
5716                                &Printer->jobid);
5717
5718         /* An error occured in print_job_start() so return an appropriate
5719            NT error code. */
5720
5721         if (!W_ERROR_IS_OK(werr)) {
5722                 return werr;
5723         }
5724
5725         Printer->document_started = true;
5726         *r->out.job_id = Printer->jobid;
5727
5728         return WERR_OK;
5729 }
5730
5731 /****************************************************************
5732  _spoolss_EndDocPrinter
5733 ****************************************************************/
5734
5735 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5736                               struct spoolss_EndDocPrinter *r)
5737 {
5738         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5739         NTSTATUS status;
5740         int snum;
5741
5742         if (!Printer) {
5743                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5744                         OUR_HANDLE(r->in.handle)));
5745                 return WERR_BADFID;
5746         }
5747
5748         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5749                 return WERR_BADFID;
5750         }
5751
5752         Printer->document_started = false;
5753         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5754         if (!NT_STATUS_IS_OK(status)) {
5755                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5756                           "print_job_end failed [%s]\n",
5757                           nt_errstr(status)));
5758         }
5759
5760         Printer->jobid = 0;
5761         return ntstatus_to_werror(status);
5762 }
5763
5764 /****************************************************************
5765  _spoolss_WritePrinter
5766 ****************************************************************/
5767
5768 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5769                              struct spoolss_WritePrinter *r)
5770 {
5771         ssize_t buffer_written;
5772         int snum;
5773         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5774
5775         if (!Printer) {
5776                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5777                         OUR_HANDLE(r->in.handle)));
5778                 *r->out.num_written = r->in._data_size;
5779                 return WERR_BADFID;
5780         }
5781
5782         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5783                 return WERR_BADFID;
5784
5785         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5786         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5787                                                    snum, Printer->jobid,
5788                                                    (const char *)r->in.data.data,
5789                                                    (size_t)r->in._data_size);
5790         if (buffer_written == (ssize_t)-1) {
5791                 *r->out.num_written = 0;
5792                 if (errno == ENOSPC)
5793                         return WERR_NO_SPOOL_SPACE;
5794                 else
5795                         return WERR_ACCESS_DENIED;
5796         }
5797
5798         *r->out.num_written = r->in._data_size;
5799
5800         return WERR_OK;
5801 }
5802
5803 /********************************************************************
5804  * api_spoolss_getprinter
5805  * called from the spoolss dispatcher
5806  *
5807  ********************************************************************/
5808
5809 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5810                               struct pipes_struct *p)
5811 {
5812         const struct auth_serversupplied_info *session_info = p->session_info;
5813         int snum;
5814         WERROR errcode = WERR_BADFUNC;
5815         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5816
5817         if (!Printer) {
5818                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5819                         OUR_HANDLE(handle)));
5820                 return WERR_BADFID;
5821         }
5822
5823         if (!get_printer_snum(p, handle, &snum, NULL))
5824                 return WERR_BADFID;
5825
5826         switch (command) {
5827         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5828                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5829                 break;
5830         case SPOOLSS_PRINTER_CONTROL_RESUME:
5831         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5832                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5833                 break;
5834         case SPOOLSS_PRINTER_CONTROL_PURGE:
5835                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5836                 break;
5837         default:
5838                 return WERR_UNKNOWN_LEVEL;
5839         }
5840
5841         return errcode;
5842 }
5843
5844
5845 /****************************************************************
5846  _spoolss_AbortPrinter
5847  * From MSDN: "Deletes printer's spool file if printer is configured
5848  * for spooling"
5849 ****************************************************************/
5850
5851 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5852                              struct spoolss_AbortPrinter *r)
5853 {
5854         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5855         int             snum;
5856         WERROR          errcode = WERR_OK;
5857
5858         if (!Printer) {
5859                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5860                         OUR_HANDLE(r->in.handle)));
5861                 return WERR_BADFID;
5862         }
5863
5864         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5865                 return WERR_BADFID;
5866
5867         if (!Printer->document_started) {
5868                 return WERR_SPL_NO_STARTDOC;
5869         }
5870
5871         errcode = print_job_delete(p->session_info,
5872                                    p->msg_ctx,
5873                                    snum,
5874                                    Printer->jobid);
5875
5876         return errcode;
5877 }
5878
5879 /********************************************************************
5880  * called by spoolss_api_setprinter
5881  * when updating a printer description
5882  ********************************************************************/
5883
5884 static WERROR update_printer_sec(struct policy_handle *handle,
5885                                  struct pipes_struct *p,
5886                                  struct sec_desc_buf *secdesc_ctr)
5887 {
5888         struct spoolss_security_descriptor *new_secdesc = NULL;
5889         struct spoolss_security_descriptor *old_secdesc = NULL;
5890         const char *printer;
5891         WERROR result;
5892         int snum;
5893
5894         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5895
5896         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5897                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5898                          OUR_HANDLE(handle)));
5899
5900                 result = WERR_BADFID;
5901                 goto done;
5902         }
5903
5904         if (secdesc_ctr == NULL) {
5905                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5906                 result = WERR_INVALID_PARAM;
5907                 goto done;
5908         }
5909         printer = lp_const_servicename(snum);
5910
5911         /* Check the user has permissions to change the security
5912            descriptor.  By experimentation with two NT machines, the user
5913            requires Full Access to the printer to change security
5914            information. */
5915
5916         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5917                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5918                 result = WERR_ACCESS_DENIED;
5919                 goto done;
5920         }
5921
5922         /* NT seems to like setting the security descriptor even though
5923            nothing may have actually changed. */
5924         result = winreg_get_printer_secdesc(p->mem_ctx,
5925                                             get_session_info_system(),
5926                                             p->msg_ctx,
5927                                             printer,
5928                                             &old_secdesc);
5929         if (!W_ERROR_IS_OK(result)) {
5930                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5931                 result = WERR_BADFID;
5932                 goto done;
5933         }
5934
5935         if (DEBUGLEVEL >= 10) {
5936                 struct security_acl *the_acl;
5937                 int i;
5938
5939                 the_acl = old_secdesc->dacl;
5940                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5941                            printer, the_acl->num_aces));
5942
5943                 for (i = 0; i < the_acl->num_aces; i++) {
5944                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5945                                            &the_acl->aces[i].trustee),
5946                                   the_acl->aces[i].access_mask));
5947                 }
5948
5949                 the_acl = secdesc_ctr->sd->dacl;
5950
5951                 if (the_acl) {
5952                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5953                                    printer, the_acl->num_aces));
5954
5955                         for (i = 0; i < the_acl->num_aces; i++) {
5956                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5957                                                    &the_acl->aces[i].trustee),
5958                                            the_acl->aces[i].access_mask));
5959                         }
5960                 } else {
5961                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5962                 }
5963         }
5964
5965         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5966         if (new_secdesc == NULL) {
5967                 result = WERR_NOMEM;
5968                 goto done;
5969         }
5970
5971         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5972                 result = WERR_OK;
5973                 goto done;
5974         }
5975
5976         result = winreg_set_printer_secdesc(p->mem_ctx,
5977                                             get_session_info_system(),
5978                                             p->msg_ctx,
5979                                             printer,
5980                                             new_secdesc);
5981
5982  done:
5983         return result;
5984 }
5985
5986 /********************************************************************
5987  Canonicalize printer info from a client
5988  ********************************************************************/
5989
5990 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5991                              struct spoolss_SetPrinterInfo2 *info2,
5992                              int snum)
5993 {
5994         fstring printername;
5995         const char *p;
5996
5997         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5998                 "portname=%s drivername=%s comment=%s location=%s\n",
5999                 info2->servername, info2->printername, info2->sharename,
6000                 info2->portname, info2->drivername, info2->comment,
6001                 info2->location));
6002
6003         /* we force some elements to "correct" values */
6004         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6005         if (info2->servername == NULL) {
6006                 return false;
6007         }
6008         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6009         if (info2->sharename == NULL) {
6010                 return false;
6011         }
6012
6013         /* check to see if we allow printername != sharename */
6014         if (lp_force_printername(snum)) {
6015                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6016                                         global_myname(), info2->sharename);
6017         } else {
6018                 /* make sure printername is in \\server\printername format */
6019                 fstrcpy(printername, info2->printername);
6020                 p = printername;
6021                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6022                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6023                                 p++;
6024                 }
6025
6026                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6027                                         global_myname(), p);
6028         }
6029         if (info2->printername == NULL) {
6030                 return false;
6031         }
6032
6033         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6034         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6035
6036         return true;
6037 }
6038
6039 /****************************************************************************
6040 ****************************************************************************/
6041
6042 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6043 {
6044         char *cmd = lp_addport_cmd();
6045         char *command = NULL;
6046         int ret;
6047         bool is_print_op = false;
6048
6049         if ( !*cmd ) {
6050                 return WERR_ACCESS_DENIED;
6051         }
6052
6053         command = talloc_asprintf(ctx,
6054                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6055         if (!command) {
6056                 return WERR_NOMEM;
6057         }
6058
6059         if ( token )
6060                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6061
6062         DEBUG(10,("Running [%s]\n", command));
6063
6064         /********* BEGIN SePrintOperatorPrivilege **********/
6065
6066         if ( is_print_op )
6067                 become_root();
6068
6069         ret = smbrun(command, NULL);
6070
6071         if ( is_print_op )
6072                 unbecome_root();
6073
6074         /********* END SePrintOperatorPrivilege **********/
6075
6076         DEBUGADD(10,("returned [%d]\n", ret));
6077
6078         TALLOC_FREE(command);
6079
6080         if ( ret != 0 ) {
6081                 return WERR_ACCESS_DENIED;
6082         }
6083
6084         return WERR_OK;
6085 }
6086
6087 /****************************************************************************
6088 ****************************************************************************/
6089
6090 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6091                              struct spoolss_SetPrinterInfo2 *info2,
6092                              const char *remote_machine,
6093                              struct messaging_context *msg_ctx)
6094 {
6095         char *cmd = lp_addprinter_cmd();
6096         char **qlines;
6097         char *command = NULL;
6098         int numlines;
6099         int ret;
6100         int fd;
6101         bool is_print_op = false;
6102
6103         if (!remote_machine) {
6104                 return false;
6105         }
6106
6107         command = talloc_asprintf(ctx,
6108                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6109                         cmd, info2->printername, info2->sharename,
6110                         info2->portname, info2->drivername,
6111                         info2->location, info2->comment, remote_machine);
6112         if (!command) {
6113                 return false;
6114         }
6115
6116         if ( token )
6117                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6118
6119         DEBUG(10,("Running [%s]\n", command));
6120
6121         /********* BEGIN SePrintOperatorPrivilege **********/
6122
6123         if ( is_print_op )
6124                 become_root();
6125
6126         if ( (ret = smbrun(command, &fd)) == 0 ) {
6127                 /* Tell everyone we updated smb.conf. */
6128                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6129         }
6130
6131         if ( is_print_op )
6132                 unbecome_root();
6133
6134         /********* END SePrintOperatorPrivilege **********/
6135
6136         DEBUGADD(10,("returned [%d]\n", ret));
6137
6138         TALLOC_FREE(command);
6139
6140         if ( ret != 0 ) {
6141                 if (fd != -1)
6142                         close(fd);
6143                 return false;
6144         }
6145
6146         /* reload our services immediately */
6147         become_root();
6148         reload_services(msg_ctx, -1, false);
6149         unbecome_root();
6150
6151         numlines = 0;
6152         /* Get lines and convert them back to dos-codepage */
6153         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6154         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6155         close(fd);
6156
6157         /* Set the portname to what the script says the portname should be. */
6158         /* but don't require anything to be return from the script exit a good error code */
6159
6160         if (numlines) {
6161                 /* Set the portname to what the script says the portname should be. */
6162                 info2->portname = talloc_strdup(ctx, qlines[0]);
6163                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6164         }
6165
6166         TALLOC_FREE(qlines);
6167         return true;
6168 }
6169
6170 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6171                                const struct auth_serversupplied_info *session_info,
6172                                struct messaging_context *msg_ctx,
6173                                int snum,
6174                                struct spoolss_SetPrinterInfo2 *printer,
6175                                struct spoolss_PrinterInfo2 *old_printer)
6176 {
6177         bool force_update = (old_printer == NULL);
6178         const char *dnsdomname;
6179         const char *longname;
6180         const char *uncname;
6181         const char *spooling;
6182         DATA_BLOB buffer;
6183         WERROR result = WERR_OK;
6184
6185         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6186                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6187                 winreg_set_printer_dataex(mem_ctx,
6188                                           session_info,
6189                                           msg_ctx,
6190                                           printer->sharename,
6191                                           SPOOL_DSSPOOLER_KEY,
6192                                           SPOOL_REG_DRIVERNAME,
6193                                           REG_SZ,
6194                                           buffer.data,
6195                                           buffer.length);
6196
6197                 if (!force_update) {
6198                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6199                                 printer->drivername));
6200
6201                         notify_printer_driver(server_event_context(), msg_ctx,
6202                                               snum, printer->drivername ?
6203                                               printer->drivername : "");
6204                 }
6205         }
6206
6207         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6208                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6209                 winreg_set_printer_dataex(mem_ctx,
6210                                           session_info,
6211                                           msg_ctx,
6212                                           printer->sharename,
6213                                           SPOOL_DSSPOOLER_KEY,
6214                                           SPOOL_REG_DESCRIPTION,
6215                                           REG_SZ,
6216                                           buffer.data,
6217                                           buffer.length);
6218
6219                 if (!force_update) {
6220                         notify_printer_comment(server_event_context(), msg_ctx,
6221                                                snum, printer->comment ?
6222                                                printer->comment : "");
6223                 }
6224         }
6225
6226         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6227                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6228                 winreg_set_printer_dataex(mem_ctx,
6229                                           session_info,
6230                                           msg_ctx,
6231                                           printer->sharename,
6232                                           SPOOL_DSSPOOLER_KEY,
6233                                           SPOOL_REG_PRINTSHARENAME,
6234                                           REG_SZ,
6235                                           buffer.data,
6236                                           buffer.length);
6237
6238                 if (!force_update) {
6239                         notify_printer_sharename(server_event_context(),
6240                                                  msg_ctx,
6241                                                  snum, printer->sharename ?
6242                                                  printer->sharename : "");
6243                 }
6244         }
6245
6246         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6247                 const char *p;
6248
6249                 p = strrchr(printer->printername, '\\' );
6250                 if (p != NULL) {
6251                         p++;
6252                 } else {
6253                         p = printer->printername;
6254                 }
6255
6256                 push_reg_sz(mem_ctx, &buffer, p);
6257                 winreg_set_printer_dataex(mem_ctx,
6258                                           session_info,
6259                                           msg_ctx,
6260                                           printer->sharename,
6261                                           SPOOL_DSSPOOLER_KEY,
6262                                           SPOOL_REG_PRINTERNAME,
6263                                           REG_SZ,
6264                                           buffer.data,
6265                                           buffer.length);
6266
6267                 if (!force_update) {
6268                         notify_printer_printername(server_event_context(),
6269                                                    msg_ctx, snum, p ? p : "");
6270                 }
6271         }
6272
6273         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6274                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6275                 winreg_set_printer_dataex(mem_ctx,
6276                                           session_info,
6277                                           msg_ctx,
6278                                           printer->sharename,
6279                                           SPOOL_DSSPOOLER_KEY,
6280                                           SPOOL_REG_PORTNAME,
6281                                           REG_SZ,
6282                                           buffer.data,
6283                                           buffer.length);
6284
6285                 if (!force_update) {
6286                         notify_printer_port(server_event_context(),
6287                                             msg_ctx, snum, printer->portname ?
6288                                             printer->portname : "");
6289                 }
6290         }
6291
6292         if (force_update || !strequal(printer->location, old_printer->location)) {
6293                 push_reg_sz(mem_ctx, &buffer, printer->location);
6294                 winreg_set_printer_dataex(mem_ctx,
6295                                           session_info,
6296                                           msg_ctx,
6297                                           printer->sharename,
6298                                           SPOOL_DSSPOOLER_KEY,
6299                                           SPOOL_REG_LOCATION,
6300                                           REG_SZ,
6301                                           buffer.data,
6302                                           buffer.length);
6303
6304                 if (!force_update) {
6305                         notify_printer_location(server_event_context(),
6306                                                 msg_ctx, snum,
6307                                                 printer->location ?
6308                                                 printer->location : "");
6309                 }
6310         }
6311
6312         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6313                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6314                 winreg_set_printer_dataex(mem_ctx,
6315                                           session_info,
6316                                           msg_ctx,
6317                                           printer->sharename,
6318                                           SPOOL_DSSPOOLER_KEY,
6319                                           SPOOL_REG_PRINTSEPARATORFILE,
6320                                           REG_SZ,
6321                                           buffer.data,
6322                                           buffer.length);
6323
6324                 if (!force_update) {
6325                         notify_printer_sepfile(server_event_context(),
6326                                                msg_ctx, snum,
6327                                                printer->sepfile ?
6328                                                printer->sepfile : "");
6329                 }
6330         }
6331
6332         if (force_update || printer->starttime != old_printer->starttime) {
6333                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6334                 SIVAL(buffer.data, 0, printer->starttime);
6335                 winreg_set_printer_dataex(mem_ctx,
6336                                           session_info,
6337                                           msg_ctx,
6338                                           printer->sharename,
6339                                           SPOOL_DSSPOOLER_KEY,
6340                                           SPOOL_REG_PRINTSTARTTIME,
6341                                           REG_DWORD,
6342                                           buffer.data,
6343                                           buffer.length);
6344         }
6345
6346         if (force_update || printer->untiltime != old_printer->untiltime) {
6347                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6348                 SIVAL(buffer.data, 0, printer->untiltime);
6349                 winreg_set_printer_dataex(mem_ctx,
6350                                           session_info,
6351                                           msg_ctx,
6352                                           printer->sharename,
6353                                           SPOOL_DSSPOOLER_KEY,
6354                                           SPOOL_REG_PRINTENDTIME,
6355                                           REG_DWORD,
6356                                           buffer.data,
6357                                           buffer.length);
6358         }
6359
6360         if (force_update || printer->priority != old_printer->priority) {
6361                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6362                 SIVAL(buffer.data, 0, printer->priority);
6363                 winreg_set_printer_dataex(mem_ctx,
6364                                           session_info,
6365                                           msg_ctx,
6366                                           printer->sharename,
6367                                           SPOOL_DSSPOOLER_KEY,
6368                                           SPOOL_REG_PRIORITY,
6369                                           REG_DWORD,
6370                                           buffer.data,
6371                                           buffer.length);
6372         }
6373
6374         if (force_update || printer->attributes != old_printer->attributes) {
6375                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6376                 SIVAL(buffer.data, 0, (printer->attributes &
6377                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6378                 winreg_set_printer_dataex(mem_ctx,
6379                                           session_info,
6380                                           msg_ctx,
6381                                           printer->sharename,
6382                                           SPOOL_DSSPOOLER_KEY,
6383                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6384                                           REG_DWORD,
6385                                           buffer.data,
6386                                           buffer.length);
6387
6388                 switch (printer->attributes & 0x3) {
6389                         case 0:
6390                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6391                                 break;
6392                         case 1:
6393                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6394                                 break;
6395                         case 2:
6396                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6397                                 break;
6398                         default:
6399                                 spooling = "unknown";
6400                 }
6401                 push_reg_sz(mem_ctx, &buffer, spooling);
6402                 winreg_set_printer_dataex(mem_ctx,
6403                                           session_info,
6404                                           msg_ctx,
6405                                           printer->sharename,
6406                                           SPOOL_DSSPOOLER_KEY,
6407                                           SPOOL_REG_PRINTSPOOLING,
6408                                           REG_SZ,
6409                                           buffer.data,
6410                                           buffer.length);
6411         }
6412
6413         push_reg_sz(mem_ctx, &buffer, global_myname());
6414         winreg_set_printer_dataex(mem_ctx,
6415                                   session_info,
6416                                   msg_ctx,
6417                                   printer->sharename,
6418                                   SPOOL_DSSPOOLER_KEY,
6419                                   SPOOL_REG_SHORTSERVERNAME,
6420                                   REG_SZ,
6421                                   buffer.data,
6422                                   buffer.length);
6423
6424         dnsdomname = get_mydnsfullname();
6425         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6426                 longname = talloc_strdup(mem_ctx, dnsdomname);
6427         } else {
6428                 longname = talloc_strdup(mem_ctx, global_myname());
6429         }
6430         if (longname == NULL) {
6431                 result = WERR_NOMEM;
6432                 goto done;
6433         }
6434
6435         push_reg_sz(mem_ctx, &buffer, longname);
6436         winreg_set_printer_dataex(mem_ctx,
6437                                   session_info,
6438                                   msg_ctx,
6439                                   printer->sharename,
6440                                   SPOOL_DSSPOOLER_KEY,
6441                                   SPOOL_REG_SERVERNAME,
6442                                   REG_SZ,
6443                                   buffer.data,
6444                                   buffer.length);
6445
6446         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6447                                   global_myname(), printer->sharename);
6448         push_reg_sz(mem_ctx, &buffer, uncname);
6449         winreg_set_printer_dataex(mem_ctx,
6450                                   session_info,
6451                                   msg_ctx,
6452                                   printer->sharename,
6453                                   SPOOL_DSSPOOLER_KEY,
6454                                   SPOOL_REG_UNCNAME,
6455                                   REG_SZ,
6456                                   buffer.data,
6457                                   buffer.length);
6458
6459 done:
6460         return result;
6461 }
6462
6463 /********************************************************************
6464  * Called by spoolss_api_setprinter
6465  * when updating a printer description.
6466  ********************************************************************/
6467
6468 static WERROR update_printer(struct pipes_struct *p,
6469                              struct policy_handle *handle,
6470                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6471                              struct spoolss_DeviceMode *devmode)
6472 {
6473         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6474         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6475         struct spoolss_PrinterInfo2 *old_printer;
6476         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6477         int snum;
6478         WERROR result = WERR_OK;
6479         TALLOC_CTX *tmp_ctx;
6480
6481         DEBUG(8,("update_printer\n"));
6482
6483         tmp_ctx = talloc_new(p->mem_ctx);
6484         if (tmp_ctx == NULL) {
6485                 return WERR_NOMEM;
6486         }
6487
6488         if (!Printer) {
6489                 result = WERR_BADFID;
6490                 goto done;
6491         }
6492
6493         if (!get_printer_snum(p, handle, &snum, NULL)) {
6494                 result = WERR_BADFID;
6495                 goto done;
6496         }
6497
6498         result = winreg_get_printer(tmp_ctx,
6499                                     get_session_info_system(),
6500                                     p->msg_ctx,
6501                                     lp_const_servicename(snum),
6502                                     &old_printer);
6503         if (!W_ERROR_IS_OK(result)) {
6504                 result = WERR_BADFID;
6505                 goto done;
6506         }
6507
6508         /* Do sanity check on the requested changes for Samba */
6509         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6510                 result = WERR_INVALID_PARAM;
6511                 goto done;
6512         }
6513
6514         /* FIXME!!! If the driver has changed we really should verify that
6515            it is installed before doing much else   --jerry */
6516
6517         /* Check calling user has permission to update printer description */
6518         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6519                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6520                 result = WERR_ACCESS_DENIED;
6521                 goto done;
6522         }
6523
6524         /* Call addprinter hook */
6525         /* Check changes to see if this is really needed */
6526
6527         if (*lp_addprinter_cmd() &&
6528                         (!strequal(printer->drivername, old_printer->drivername) ||
6529                          !strequal(printer->comment, old_printer->comment) ||
6530                          !strequal(printer->portname, old_printer->portname) ||
6531                          !strequal(printer->location, old_printer->location)) )
6532         {
6533                 /* add_printer_hook() will call reload_services() */
6534                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6535                                       printer, p->client_id->addr,
6536                                       p->msg_ctx)) {
6537                         result = WERR_ACCESS_DENIED;
6538                         goto done;
6539                 }
6540         }
6541
6542         update_dsspooler(tmp_ctx,
6543                          get_session_info_system(),
6544                          p->msg_ctx,
6545                          snum,
6546                          printer,
6547                          old_printer);
6548
6549         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6550
6551         if (devmode == NULL) {
6552                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6553         }
6554         result = winreg_update_printer(tmp_ctx,
6555                                        get_session_info_system(),
6556                                        p->msg_ctx,
6557                                        printer->sharename,
6558                                        printer_mask,
6559                                        printer,
6560                                        devmode,
6561                                        NULL);
6562
6563 done:
6564         talloc_free(tmp_ctx);
6565
6566         return result;
6567 }
6568
6569 /****************************************************************************
6570 ****************************************************************************/
6571 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6572                                            struct policy_handle *handle,
6573                                            struct spoolss_SetPrinterInfo7 *info7)
6574 {
6575 #ifdef HAVE_ADS
6576         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6577         WERROR result;
6578         int snum;
6579         struct printer_handle *Printer;
6580
6581         if ( lp_security() != SEC_ADS ) {
6582                 return WERR_UNKNOWN_LEVEL;
6583         }
6584
6585         Printer = find_printer_index_by_hnd(p, handle);
6586
6587         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6588
6589         if (!Printer)
6590                 return WERR_BADFID;
6591
6592         if (!get_printer_snum(p, handle, &snum, NULL))
6593                 return WERR_BADFID;
6594
6595         result = winreg_get_printer(p->mem_ctx,
6596                                     get_session_info_system(),
6597                                     p->msg_ctx,
6598                                     lp_servicename(snum),
6599                                     &pinfo2);
6600         if (!W_ERROR_IS_OK(result)) {
6601                 return WERR_BADFID;
6602         }
6603
6604         nt_printer_publish(pinfo2,
6605                            get_session_info_system(),
6606                            p->msg_ctx,
6607                            pinfo2,
6608                            info7->action);
6609
6610         TALLOC_FREE(pinfo2);
6611         return WERR_OK;
6612 #else
6613         return WERR_UNKNOWN_LEVEL;
6614 #endif
6615 }
6616
6617 /********************************************************************
6618  ********************************************************************/
6619
6620 static WERROR update_printer_devmode(struct pipes_struct *p,
6621                                      struct policy_handle *handle,
6622                                      struct spoolss_DeviceMode *devmode)
6623 {
6624         int snum;
6625         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6626         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6627
6628         DEBUG(8,("update_printer_devmode\n"));
6629
6630         if (!Printer) {
6631                 return WERR_BADFID;
6632         }
6633
6634         if (!get_printer_snum(p, handle, &snum, NULL)) {
6635                 return WERR_BADFID;
6636         }
6637
6638         /* Check calling user has permission to update printer description */
6639         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6640                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6641                 return WERR_ACCESS_DENIED;
6642         }
6643
6644         return winreg_update_printer(p->mem_ctx,
6645                                      get_session_info_system(),
6646                                      p->msg_ctx,
6647                                      lp_const_servicename(snum),
6648                                      info2_mask,
6649                                      NULL,
6650                                      devmode,
6651                                      NULL);
6652 }
6653
6654
6655 /****************************************************************
6656  _spoolss_SetPrinter
6657 ****************************************************************/
6658
6659 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6660                            struct spoolss_SetPrinter *r)
6661 {
6662         WERROR result;
6663
6664         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6665
6666         if (!Printer) {
6667                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6668                         OUR_HANDLE(r->in.handle)));
6669                 return WERR_BADFID;
6670         }
6671
6672         /* check the level */
6673         switch (r->in.info_ctr->level) {
6674                 case 0:
6675                         return control_printer(r->in.handle, r->in.command, p);
6676                 case 2:
6677                         result = update_printer(p, r->in.handle,
6678                                                 r->in.info_ctr,
6679                                                 r->in.devmode_ctr->devmode);
6680                         if (!W_ERROR_IS_OK(result))
6681                                 return result;
6682                         if (r->in.secdesc_ctr->sd)
6683                                 result = update_printer_sec(r->in.handle, p,
6684                                                             r->in.secdesc_ctr);
6685                         return result;
6686                 case 3:
6687                         return update_printer_sec(r->in.handle, p,
6688                                                   r->in.secdesc_ctr);
6689                 case 7:
6690                         return publish_or_unpublish_printer(p, r->in.handle,
6691                                                             r->in.info_ctr->info.info7);
6692                 case 8:
6693                         return update_printer_devmode(p, r->in.handle,
6694                                                       r->in.devmode_ctr->devmode);
6695                 default:
6696                         return WERR_UNKNOWN_LEVEL;
6697         }
6698 }
6699
6700 /****************************************************************
6701  _spoolss_FindClosePrinterNotify
6702 ****************************************************************/
6703
6704 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6705                                        struct spoolss_FindClosePrinterNotify *r)
6706 {
6707         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6708
6709         if (!Printer) {
6710                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6711                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6712                 return WERR_BADFID;
6713         }
6714
6715         if (Printer->notify.cli_chan != NULL &&
6716             Printer->notify.cli_chan->active_connections > 0) {
6717                 int snum = -1;
6718
6719                 if (Printer->printer_type == SPLHND_PRINTER) {
6720                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6721                                 return WERR_BADFID;
6722                         }
6723                 }
6724
6725                 srv_spoolss_replycloseprinter(snum, Printer);
6726         }
6727
6728         Printer->notify.flags=0;
6729         Printer->notify.options=0;
6730         Printer->notify.localmachine[0]='\0';
6731         Printer->notify.printerlocal=0;
6732         TALLOC_FREE(Printer->notify.option);
6733
6734         return WERR_OK;
6735 }
6736
6737 /****************************************************************
6738  _spoolss_AddJob
6739 ****************************************************************/
6740
6741 WERROR _spoolss_AddJob(struct pipes_struct *p,
6742                        struct spoolss_AddJob *r)
6743 {
6744         if (!r->in.buffer && (r->in.offered != 0)) {
6745                 return WERR_INVALID_PARAM;
6746         }
6747
6748         /* this is what a NT server returns for AddJob. AddJob must fail on
6749          * non-local printers */
6750
6751         if (r->in.level != 1) {
6752                 return WERR_UNKNOWN_LEVEL;
6753         }
6754
6755         return WERR_INVALID_PARAM;
6756 }
6757
6758 /****************************************************************************
6759 fill_job_info1
6760 ****************************************************************************/
6761
6762 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6763                              struct spoolss_JobInfo1 *r,
6764                              const print_queue_struct *queue,
6765                              int position, int snum,
6766                              struct spoolss_PrinterInfo2 *pinfo2)
6767 {
6768         struct tm *t;
6769
6770         t = gmtime(&queue->time);
6771
6772         r->job_id               = queue->job;
6773
6774         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6775         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6776         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6777         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6778         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6779         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6780         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6781         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6782         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6783         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6784         r->text_status          = talloc_strdup(mem_ctx, "");
6785         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6786
6787         r->status               = nt_printj_status(queue->status);
6788         r->priority             = queue->priority;
6789         r->position             = position;
6790         r->total_pages          = queue->page_count;
6791         r->pages_printed        = 0; /* ??? */
6792
6793         init_systemtime(&r->submitted, t);
6794
6795         return WERR_OK;
6796 }
6797
6798 /****************************************************************************
6799 fill_job_info2
6800 ****************************************************************************/
6801
6802 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6803                              struct spoolss_JobInfo2 *r,
6804                              const print_queue_struct *queue,
6805                              int position, int snum,
6806                              struct spoolss_PrinterInfo2 *pinfo2,
6807                              struct spoolss_DeviceMode *devmode)
6808 {
6809         struct tm *t;
6810
6811         t = gmtime(&queue->time);
6812
6813         r->job_id               = queue->job;
6814
6815         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6816         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6817         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6818         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6819         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6820         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6821         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6822         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6823         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6824         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6825         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6826         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6827         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6828         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6829         r->parameters           = talloc_strdup(mem_ctx, "");
6830         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6831         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6832         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6833
6834         r->devmode              = devmode;
6835
6836         r->text_status          = talloc_strdup(mem_ctx, "");
6837         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6838
6839         r->secdesc              = NULL;
6840
6841         r->status               = nt_printj_status(queue->status);
6842         r->priority             = queue->priority;
6843         r->position             = position;
6844         r->start_time           = 0;
6845         r->until_time           = 0;
6846         r->total_pages          = queue->page_count;
6847         r->size                 = queue->size;
6848         init_systemtime(&r->submitted, t);
6849         r->time                 = 0;
6850         r->pages_printed        = 0; /* ??? */
6851
6852         return WERR_OK;
6853 }
6854
6855 /****************************************************************************
6856 fill_job_info3
6857 ****************************************************************************/
6858
6859 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6860                              struct spoolss_JobInfo3 *r,
6861                              const print_queue_struct *queue,
6862                              const print_queue_struct *next_queue,
6863                              int position, int snum,
6864                              struct spoolss_PrinterInfo2 *pinfo2)
6865 {
6866         r->job_id               = queue->job;
6867         r->next_job_id          = 0;
6868         if (next_queue) {
6869                 r->next_job_id  = next_queue->job;
6870         }
6871         r->reserved             = 0;
6872
6873         return WERR_OK;
6874 }
6875
6876 /****************************************************************************
6877  Enumjobs at level 1.
6878 ****************************************************************************/
6879
6880 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6881                               const print_queue_struct *queue,
6882                               uint32_t num_queues, int snum,
6883                               struct spoolss_PrinterInfo2 *pinfo2,
6884                               union spoolss_JobInfo **info_p,
6885                               uint32_t *count)
6886 {
6887         union spoolss_JobInfo *info;
6888         int i;
6889         WERROR result = WERR_OK;
6890
6891         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6892         W_ERROR_HAVE_NO_MEMORY(info);
6893
6894         *count = num_queues;
6895
6896         for (i=0; i<*count; i++) {
6897                 result = fill_job_info1(info,
6898                                         &info[i].info1,
6899                                         &queue[i],
6900                                         i,
6901                                         snum,
6902                                         pinfo2);
6903                 if (!W_ERROR_IS_OK(result)) {
6904                         goto out;
6905                 }
6906         }
6907
6908  out:
6909         if (!W_ERROR_IS_OK(result)) {
6910                 TALLOC_FREE(info);
6911                 *count = 0;
6912                 return result;
6913         }
6914
6915         *info_p = info;
6916
6917         return WERR_OK;
6918 }
6919
6920 /****************************************************************************
6921  Enumjobs at level 2.
6922 ****************************************************************************/
6923
6924 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6925                               const print_queue_struct *queue,
6926                               uint32_t num_queues, int snum,
6927                               struct spoolss_PrinterInfo2 *pinfo2,
6928                               union spoolss_JobInfo **info_p,
6929                               uint32_t *count)
6930 {
6931         union spoolss_JobInfo *info;
6932         int i;
6933         WERROR result = WERR_OK;
6934
6935         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6936         W_ERROR_HAVE_NO_MEMORY(info);
6937
6938         *count = num_queues;
6939
6940         for (i=0; i<*count; i++) {
6941                 struct spoolss_DeviceMode *devmode;
6942
6943                 result = spoolss_create_default_devmode(info,
6944                                                         pinfo2->printername,
6945                                                         &devmode);
6946                 if (!W_ERROR_IS_OK(result)) {
6947                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6948                         goto out;
6949                 }
6950
6951                 result = fill_job_info2(info,
6952                                         &info[i].info2,
6953                                         &queue[i],
6954                                         i,
6955                                         snum,
6956                                         pinfo2,
6957                                         devmode);
6958                 if (!W_ERROR_IS_OK(result)) {
6959                         goto out;
6960                 }
6961         }
6962
6963  out:
6964         if (!W_ERROR_IS_OK(result)) {
6965                 TALLOC_FREE(info);
6966                 *count = 0;
6967                 return result;
6968         }
6969
6970         *info_p = info;
6971
6972         return WERR_OK;
6973 }
6974
6975 /****************************************************************************
6976  Enumjobs at level 3.
6977 ****************************************************************************/
6978
6979 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6980                               const print_queue_struct *queue,
6981                               uint32_t num_queues, int snum,
6982                               struct spoolss_PrinterInfo2 *pinfo2,
6983                               union spoolss_JobInfo **info_p,
6984                               uint32_t *count)
6985 {
6986         union spoolss_JobInfo *info;
6987         int i;
6988         WERROR result = WERR_OK;
6989
6990         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6991         W_ERROR_HAVE_NO_MEMORY(info);
6992
6993         *count = num_queues;
6994
6995         for (i=0; i<*count; i++) {
6996                 const print_queue_struct *next_queue = NULL;
6997
6998                 if (i+1 < *count) {
6999                         next_queue = &queue[i+1];
7000                 }
7001
7002                 result = fill_job_info3(info,
7003                                         &info[i].info3,
7004                                         &queue[i],
7005                                         next_queue,
7006                                         i,
7007                                         snum,
7008                                         pinfo2);
7009                 if (!W_ERROR_IS_OK(result)) {
7010                         goto out;
7011                 }
7012         }
7013
7014  out:
7015         if (!W_ERROR_IS_OK(result)) {
7016                 TALLOC_FREE(info);
7017                 *count = 0;
7018                 return result;
7019         }
7020
7021         *info_p = info;
7022
7023         return WERR_OK;
7024 }
7025
7026 /****************************************************************
7027  _spoolss_EnumJobs
7028 ****************************************************************/
7029
7030 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7031                          struct spoolss_EnumJobs *r)
7032 {
7033         WERROR result;
7034         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7035         int snum;
7036         print_status_struct prt_status;
7037         print_queue_struct *queue = NULL;
7038         uint32_t count;
7039
7040         /* that's an [in out] buffer */
7041
7042         if (!r->in.buffer && (r->in.offered != 0)) {
7043                 return WERR_INVALID_PARAM;
7044         }
7045
7046         DEBUG(4,("_spoolss_EnumJobs\n"));
7047
7048         *r->out.needed = 0;
7049         *r->out.count = 0;
7050         *r->out.info = NULL;
7051
7052         /* lookup the printer snum and tdb entry */
7053
7054         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7055                 return WERR_BADFID;
7056         }
7057
7058         result = winreg_get_printer(p->mem_ctx,
7059                                     get_session_info_system(),
7060                                     p->msg_ctx,
7061                                     lp_const_servicename(snum),
7062                                     &pinfo2);
7063         if (!W_ERROR_IS_OK(result)) {
7064                 return result;
7065         }
7066
7067         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7068         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7069                 count, prt_status.status, prt_status.message));
7070
7071         if (count == 0) {
7072                 SAFE_FREE(queue);
7073                 TALLOC_FREE(pinfo2);
7074                 return WERR_OK;
7075         }
7076
7077         switch (r->in.level) {
7078         case 1:
7079                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7080                                          pinfo2, r->out.info, r->out.count);
7081                 break;
7082         case 2:
7083                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7084                                          pinfo2, r->out.info, r->out.count);
7085                 break;
7086         case 3:
7087                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7088                                          pinfo2, r->out.info, r->out.count);
7089                 break;
7090         default:
7091                 result = WERR_UNKNOWN_LEVEL;
7092                 break;
7093         }
7094
7095         SAFE_FREE(queue);
7096         TALLOC_FREE(pinfo2);
7097
7098         if (!W_ERROR_IS_OK(result)) {
7099                 return result;
7100         }
7101
7102         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7103                                                      spoolss_EnumJobs,
7104                                                      *r->out.info, r->in.level,
7105                                                      *r->out.count);
7106         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7107         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7108
7109         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7110 }
7111
7112 /****************************************************************
7113  _spoolss_ScheduleJob
7114 ****************************************************************/
7115
7116 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7117                             struct spoolss_ScheduleJob *r)
7118 {
7119         return WERR_OK;
7120 }
7121
7122 /****************************************************************
7123 ****************************************************************/
7124
7125 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7126                                struct messaging_context *msg_ctx,
7127                                const char *printer_name,
7128                                uint32_t job_id,
7129                                struct spoolss_SetJobInfo1 *r)
7130 {
7131         char *old_doc_name;
7132
7133         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7134                 return WERR_BADFID;
7135         }
7136
7137         if (strequal(old_doc_name, r->document_name)) {
7138                 return WERR_OK;
7139         }
7140
7141         if (!print_job_set_name(server_event_context(), msg_ctx,
7142                                 printer_name, job_id, r->document_name)) {
7143                 return WERR_BADFID;
7144         }
7145
7146         return WERR_OK;
7147 }
7148
7149 /****************************************************************
7150  _spoolss_SetJob
7151 ****************************************************************/
7152
7153 WERROR _spoolss_SetJob(struct pipes_struct *p,
7154                        struct spoolss_SetJob *r)
7155 {
7156         const struct auth_serversupplied_info *session_info = p->session_info;
7157         int snum;
7158         WERROR errcode = WERR_BADFUNC;
7159
7160         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7161                 return WERR_BADFID;
7162         }
7163
7164         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7165                 return WERR_INVALID_PRINTER_NAME;
7166         }
7167
7168         switch (r->in.command) {
7169         case SPOOLSS_JOB_CONTROL_CANCEL:
7170         case SPOOLSS_JOB_CONTROL_DELETE:
7171                 errcode = print_job_delete(session_info, p->msg_ctx,
7172                                            snum, r->in.job_id);
7173                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7174                         errcode = WERR_OK;
7175                 }
7176                 break;
7177         case SPOOLSS_JOB_CONTROL_PAUSE:
7178                 if (print_job_pause(session_info, p->msg_ctx,
7179                                     snum, r->in.job_id, &errcode)) {
7180                         errcode = WERR_OK;
7181                 }
7182                 break;
7183         case SPOOLSS_JOB_CONTROL_RESTART:
7184         case SPOOLSS_JOB_CONTROL_RESUME:
7185                 if (print_job_resume(session_info, p->msg_ctx,
7186                                      snum, r->in.job_id, &errcode)) {
7187                         errcode = WERR_OK;
7188                 }
7189                 break;
7190         case 0:
7191                 errcode = WERR_OK;
7192                 break;
7193         default:
7194                 return WERR_UNKNOWN_LEVEL;
7195         }
7196
7197         if (!W_ERROR_IS_OK(errcode)) {
7198                 return errcode;
7199         }
7200
7201         if (r->in.ctr == NULL) {
7202                 return errcode;
7203         }
7204
7205         switch (r->in.ctr->level) {
7206         case 1:
7207                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7208                                            lp_const_servicename(snum),
7209                                            r->in.job_id,
7210                                            r->in.ctr->info.info1);
7211                 break;
7212         case 2:
7213         case 3:
7214         case 4:
7215         default:
7216                 return WERR_UNKNOWN_LEVEL;
7217         }
7218
7219         return errcode;
7220 }
7221
7222 /****************************************************************************
7223  Enumerates all printer drivers by level and architecture.
7224 ****************************************************************************/
7225
7226 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7227                                                        const struct auth_serversupplied_info *session_info,
7228                                                        struct messaging_context *msg_ctx,
7229                                                        const char *servername,
7230                                                        const char *architecture,
7231                                                        uint32_t level,
7232                                                        union spoolss_DriverInfo **info_p,
7233                                                        uint32_t *count_p)
7234 {
7235         int i;
7236         uint32_t version;
7237         struct spoolss_DriverInfo8 *driver;
7238         union spoolss_DriverInfo *info = NULL;
7239         uint32_t count = 0;
7240         WERROR result = WERR_OK;
7241         uint32_t num_drivers;
7242         const char **drivers;
7243
7244         *count_p = 0;
7245         *info_p = NULL;
7246
7247         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7248                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7249                                                 architecture, version,
7250                                                 &num_drivers, &drivers);
7251                 if (!W_ERROR_IS_OK(result)) {
7252                         goto out;
7253                 }
7254                 DEBUG(4, ("we have:[%d] drivers in environment"
7255                           " [%s] and version [%d]\n",
7256                           num_drivers, architecture, version));
7257
7258                 if (num_drivers != 0) {
7259                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7260                                                     union spoolss_DriverInfo,
7261                                                     count + num_drivers);
7262                         if (!info) {
7263                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7264                                         "failed to enlarge driver info buffer!\n"));
7265                                 result = WERR_NOMEM;
7266                                 goto out;
7267                         }
7268                 }
7269
7270                 for (i = 0; i < num_drivers; i++) {
7271                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7272
7273                         result = winreg_get_driver(mem_ctx, session_info,
7274                                                    msg_ctx,
7275                                                    architecture, drivers[i],
7276                                                    version, &driver);
7277                         if (!W_ERROR_IS_OK(result)) {
7278                                 goto out;
7279                         }
7280
7281                         switch (level) {
7282                         case 1:
7283                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7284                                                                    driver, servername);
7285                                 break;
7286                         case 2:
7287                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7288                                                                    driver, servername);
7289                                 break;
7290                         case 3:
7291                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7292                                                                    driver, servername);
7293                                 break;
7294                         case 4:
7295                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7296                                                                    driver, servername);
7297                                 break;
7298                         case 5:
7299                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7300                                                                    driver, servername);
7301                                 break;
7302                         case 6:
7303                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7304                                                                    driver, servername);
7305                                 break;
7306                         case 8:
7307                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7308                                                                    driver, servername);
7309                                 break;
7310                         default:
7311                                 result = WERR_UNKNOWN_LEVEL;
7312                                 break;
7313                         }
7314
7315                         TALLOC_FREE(driver);
7316
7317                         if (!W_ERROR_IS_OK(result)) {
7318                                 goto out;
7319                         }
7320                 }
7321
7322                 count += num_drivers;
7323                 TALLOC_FREE(drivers);
7324         }
7325
7326  out:
7327         TALLOC_FREE(drivers);
7328
7329         if (!W_ERROR_IS_OK(result)) {
7330                 TALLOC_FREE(info);
7331                 return result;
7332         }
7333
7334         *info_p = info;
7335         *count_p = count;
7336
7337         return WERR_OK;
7338 }
7339
7340 /****************************************************************************
7341  Enumerates all printer drivers by level.
7342 ****************************************************************************/
7343
7344 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7345                                        const struct auth_serversupplied_info *session_info,
7346                                        struct messaging_context *msg_ctx,
7347                                        const char *servername,
7348                                        const char *architecture,
7349                                        uint32_t level,
7350                                        union spoolss_DriverInfo **info_p,
7351                                        uint32_t *count_p)
7352 {
7353         uint32_t a,i;
7354         WERROR result = WERR_OK;
7355
7356         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7357
7358                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7359
7360                         union spoolss_DriverInfo *info = NULL;
7361                         uint32_t count = 0;
7362
7363                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7364                                                                           session_info,
7365                                                                           msg_ctx,
7366                                                                           servername,
7367                                                                           archi_table[a].long_archi,
7368                                                                           level,
7369                                                                           &info,
7370                                                                           &count);
7371                         if (!W_ERROR_IS_OK(result)) {
7372                                 continue;
7373                         }
7374
7375                         for (i=0; i < count; i++) {
7376                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7377                                              info[i], info_p, count_p);
7378                         }
7379                 }
7380
7381                 return result;
7382         }
7383
7384         return enumprinterdrivers_level_by_architecture(mem_ctx,
7385                                                         session_info,
7386                                                         msg_ctx,
7387                                                         servername,
7388                                                         architecture,
7389                                                         level,
7390                                                         info_p,
7391                                                         count_p);
7392 }
7393
7394 /****************************************************************
7395  _spoolss_EnumPrinterDrivers
7396 ****************************************************************/
7397
7398 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7399                                    struct spoolss_EnumPrinterDrivers *r)
7400 {
7401         const char *cservername;
7402         WERROR result;
7403
7404         /* that's an [in out] buffer */
7405
7406         if (!r->in.buffer && (r->in.offered != 0)) {
7407                 return WERR_INVALID_PARAM;
7408         }
7409
7410         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7411
7412         *r->out.needed = 0;
7413         *r->out.count = 0;
7414         *r->out.info = NULL;
7415
7416         cservername = canon_servername(r->in.server);
7417
7418         if (!is_myname_or_ipaddr(cservername)) {
7419                 return WERR_UNKNOWN_PRINTER_DRIVER;
7420         }
7421
7422         result = enumprinterdrivers_level(p->mem_ctx,
7423                                           get_session_info_system(),
7424                                           p->msg_ctx,
7425                                           cservername,
7426                                           r->in.environment,
7427                                           r->in.level,
7428                                           r->out.info,
7429                                           r->out.count);
7430         if (!W_ERROR_IS_OK(result)) {
7431                 return result;
7432         }
7433
7434         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7435                                                      spoolss_EnumPrinterDrivers,
7436                                                      *r->out.info, r->in.level,
7437                                                      *r->out.count);
7438         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7439         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7440
7441         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7442 }
7443
7444 /****************************************************************
7445  _spoolss_EnumForms
7446 ****************************************************************/
7447
7448 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7449                           struct spoolss_EnumForms *r)
7450 {
7451         WERROR result;
7452
7453         *r->out.count = 0;
7454         *r->out.needed = 0;
7455         *r->out.info = NULL;
7456
7457         /* that's an [in out] buffer */
7458
7459         if (!r->in.buffer && (r->in.offered != 0) ) {
7460                 return WERR_INVALID_PARAM;
7461         }
7462
7463         DEBUG(4,("_spoolss_EnumForms\n"));
7464         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7465         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7466
7467         switch (r->in.level) {
7468         case 1:
7469                 result = winreg_printer_enumforms1(p->mem_ctx,
7470                                                    get_session_info_system(),
7471                                                    p->msg_ctx,
7472                                                    r->out.count,
7473                                                    r->out.info);
7474                 break;
7475         default:
7476                 result = WERR_UNKNOWN_LEVEL;
7477                 break;
7478         }
7479
7480         if (!W_ERROR_IS_OK(result)) {
7481                 return result;
7482         }
7483
7484         if (*r->out.count == 0) {
7485                 return WERR_NO_MORE_ITEMS;
7486         }
7487
7488         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7489                                                      spoolss_EnumForms,
7490                                                      *r->out.info, r->in.level,
7491                                                      *r->out.count);
7492         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7493         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7494
7495         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7496 }
7497
7498 /****************************************************************
7499  _spoolss_GetForm
7500 ****************************************************************/
7501
7502 WERROR _spoolss_GetForm(struct pipes_struct *p,
7503                         struct spoolss_GetForm *r)
7504 {
7505         WERROR result;
7506
7507         /* that's an [in out] buffer */
7508
7509         if (!r->in.buffer && (r->in.offered != 0)) {
7510                 return WERR_INVALID_PARAM;
7511         }
7512
7513         DEBUG(4,("_spoolss_GetForm\n"));
7514         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7515         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7516
7517         switch (r->in.level) {
7518         case 1:
7519                 result = winreg_printer_getform1(p->mem_ctx,
7520                                                  get_session_info_system(),
7521                                                  p->msg_ctx,
7522                                                  r->in.form_name,
7523                                                  &r->out.info->info1);
7524                 break;
7525         default:
7526                 result = WERR_UNKNOWN_LEVEL;
7527                 break;
7528         }
7529
7530         if (!W_ERROR_IS_OK(result)) {
7531                 TALLOC_FREE(r->out.info);
7532                 return result;
7533         }
7534
7535         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7536                                                r->out.info, r->in.level);
7537         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7538
7539         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7540 }
7541
7542 /****************************************************************************
7543 ****************************************************************************/
7544
7545 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7546                           struct spoolss_PortInfo1 *r,
7547                           const char *name)
7548 {
7549         r->port_name = talloc_strdup(mem_ctx, name);
7550         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7551
7552         return WERR_OK;
7553 }
7554
7555 /****************************************************************************
7556  TODO: This probably needs distinguish between TCP/IP and Local ports
7557  somehow.
7558 ****************************************************************************/
7559
7560 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7561                           struct spoolss_PortInfo2 *r,
7562                           const char *name)
7563 {
7564         r->port_name = talloc_strdup(mem_ctx, name);
7565         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7566
7567         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7568         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7569
7570         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7571         W_ERROR_HAVE_NO_MEMORY(r->description);
7572
7573         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7574         r->reserved = 0;
7575
7576         return WERR_OK;
7577 }
7578
7579
7580 /****************************************************************************
7581  wrapper around the enumer ports command
7582 ****************************************************************************/
7583
7584 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7585 {
7586         char *cmd = lp_enumports_cmd();
7587         char **qlines = NULL;
7588         char *command = NULL;
7589         int numlines;
7590         int ret;
7591         int fd;
7592
7593         *count = 0;
7594         *lines = NULL;
7595
7596         /* if no hook then just fill in the default port */
7597
7598         if ( !*cmd ) {
7599                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7600                         return WERR_NOMEM;
7601                 }
7602                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7603                         TALLOC_FREE(qlines);
7604                         return WERR_NOMEM;
7605                 }
7606                 qlines[1] = NULL;
7607                 numlines = 1;
7608         }
7609         else {
7610                 /* we have a valid enumport command */
7611
7612                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7613                 if (!command) {
7614                         return WERR_NOMEM;
7615                 }
7616
7617                 DEBUG(10,("Running [%s]\n", command));
7618                 ret = smbrun(command, &fd);
7619                 DEBUG(10,("Returned [%d]\n", ret));
7620                 TALLOC_FREE(command);
7621                 if (ret != 0) {
7622                         if (fd != -1) {
7623                                 close(fd);
7624                         }
7625                         return WERR_ACCESS_DENIED;
7626                 }
7627
7628                 numlines = 0;
7629                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7630                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7631                 close(fd);
7632         }
7633
7634         *count = numlines;
7635         *lines = qlines;
7636
7637         return WERR_OK;
7638 }
7639
7640 /****************************************************************************
7641  enumports level 1.
7642 ****************************************************************************/
7643
7644 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7645                                 union spoolss_PortInfo **info_p,
7646                                 uint32_t *count)
7647 {
7648         union spoolss_PortInfo *info = NULL;
7649         int i=0;
7650         WERROR result = WERR_OK;
7651         char **qlines = NULL;
7652         int numlines = 0;
7653
7654         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7655         if (!W_ERROR_IS_OK(result)) {
7656                 goto out;
7657         }
7658
7659         if (numlines) {
7660                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7661                 if (!info) {
7662                         DEBUG(10,("Returning WERR_NOMEM\n"));
7663                         result = WERR_NOMEM;
7664                         goto out;
7665                 }
7666
7667                 for (i=0; i<numlines; i++) {
7668                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7669                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7670                         if (!W_ERROR_IS_OK(result)) {
7671                                 goto out;
7672                         }
7673                 }
7674         }
7675         TALLOC_FREE(qlines);
7676
7677 out:
7678         if (!W_ERROR_IS_OK(result)) {
7679                 TALLOC_FREE(info);
7680                 TALLOC_FREE(qlines);
7681                 *count = 0;
7682                 *info_p = NULL;
7683                 return result;
7684         }
7685
7686         *info_p = info;
7687         *count = numlines;
7688
7689         return WERR_OK;
7690 }
7691
7692 /****************************************************************************
7693  enumports level 2.
7694 ****************************************************************************/
7695
7696 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7697                                 union spoolss_PortInfo **info_p,
7698                                 uint32_t *count)
7699 {
7700         union spoolss_PortInfo *info = NULL;
7701         int i=0;
7702         WERROR result = WERR_OK;
7703         char **qlines = NULL;
7704         int numlines = 0;
7705
7706         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7707         if (!W_ERROR_IS_OK(result)) {
7708                 goto out;
7709         }
7710
7711         if (numlines) {
7712                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7713                 if (!info) {
7714                         DEBUG(10,("Returning WERR_NOMEM\n"));
7715                         result = WERR_NOMEM;
7716                         goto out;
7717                 }
7718
7719                 for (i=0; i<numlines; i++) {
7720                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7721                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7722                         if (!W_ERROR_IS_OK(result)) {
7723                                 goto out;
7724                         }
7725                 }
7726         }
7727         TALLOC_FREE(qlines);
7728
7729 out:
7730         if (!W_ERROR_IS_OK(result)) {
7731                 TALLOC_FREE(info);
7732                 TALLOC_FREE(qlines);
7733                 *count = 0;
7734                 *info_p = NULL;
7735                 return result;
7736         }
7737
7738         *info_p = info;
7739         *count = numlines;
7740
7741         return WERR_OK;
7742 }
7743
7744 /****************************************************************
7745  _spoolss_EnumPorts
7746 ****************************************************************/
7747
7748 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7749                           struct spoolss_EnumPorts *r)
7750 {
7751         WERROR result;
7752
7753         /* that's an [in out] buffer */
7754
7755         if (!r->in.buffer && (r->in.offered != 0)) {
7756                 return WERR_INVALID_PARAM;
7757         }
7758
7759         DEBUG(4,("_spoolss_EnumPorts\n"));
7760
7761         *r->out.count = 0;
7762         *r->out.needed = 0;
7763         *r->out.info = NULL;
7764
7765         switch (r->in.level) {
7766         case 1:
7767                 result = enumports_level_1(p->mem_ctx, r->out.info,
7768                                            r->out.count);
7769                 break;
7770         case 2:
7771                 result = enumports_level_2(p->mem_ctx, r->out.info,
7772                                            r->out.count);
7773                 break;
7774         default:
7775                 return WERR_UNKNOWN_LEVEL;
7776         }
7777
7778         if (!W_ERROR_IS_OK(result)) {
7779                 return result;
7780         }
7781
7782         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7783                                                      spoolss_EnumPorts,
7784                                                      *r->out.info, r->in.level,
7785                                                      *r->out.count);
7786         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7787         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7788
7789         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7790 }
7791
7792 /****************************************************************************
7793 ****************************************************************************/
7794
7795 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7796                                            const char *server,
7797                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7798                                            struct spoolss_DeviceMode *devmode,
7799                                            struct security_descriptor *secdesc,
7800                                            struct spoolss_UserLevelCtr *user_ctr,
7801                                            struct policy_handle *handle)
7802 {
7803         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7804         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7805         int     snum;
7806         WERROR err = WERR_OK;
7807
7808         /* samba does not have a concept of local, non-shared printers yet, so
7809          * make sure we always setup sharename - gd */
7810         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7811             (info2->printername != NULL && info2->printername[0] != '\0')) {
7812                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7813                         "no sharename has been set, setting printername %s as sharename\n",
7814                         info2->printername));
7815                 info2->sharename = info2->printername;
7816         }
7817
7818         /* check to see if the printer already exists */
7819         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7820                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7821                         info2->sharename));
7822                 return WERR_PRINTER_ALREADY_EXISTS;
7823         }
7824
7825         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7826                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7827                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7828                                 info2->printername));
7829                         return WERR_PRINTER_ALREADY_EXISTS;
7830                 }
7831         }
7832
7833         /* validate printer info struct */
7834         if (!info2->printername || strlen(info2->printername) == 0) {
7835                 return WERR_INVALID_PRINTER_NAME;
7836         }
7837         if (!info2->portname || strlen(info2->portname) == 0) {
7838                 return WERR_UNKNOWN_PORT;
7839         }
7840         if (!info2->drivername || strlen(info2->drivername) == 0) {
7841                 return WERR_UNKNOWN_PRINTER_DRIVER;
7842         }
7843         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7844                 return WERR_UNKNOWN_PRINTPROCESSOR;
7845         }
7846
7847         /* FIXME!!!  smbd should check to see if the driver is installed before
7848            trying to add a printer like this  --jerry */
7849
7850         if (*lp_addprinter_cmd() ) {
7851                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7852                                        info2, p->client_id->addr,
7853                                        p->msg_ctx) ) {
7854                         return WERR_ACCESS_DENIED;
7855                 }
7856         } else {
7857                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7858                         "smb.conf parameter \"addprinter command\" is defined. This"
7859                         "parameter must exist for this call to succeed\n",
7860                         info2->sharename ));
7861         }
7862
7863         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7864                 return WERR_ACCESS_DENIED;
7865         }
7866
7867         /* you must be a printer admin to add a new printer */
7868         if (!print_access_check(p->session_info,
7869                                 p->msg_ctx,
7870                                 snum,
7871                                 PRINTER_ACCESS_ADMINISTER)) {
7872                 return WERR_ACCESS_DENIED;
7873         }
7874
7875         /*
7876          * Do sanity check on the requested changes for Samba.
7877          */
7878
7879         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7880                 return WERR_INVALID_PARAM;
7881         }
7882
7883         if (devmode == NULL) {
7884                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7885         }
7886
7887         update_dsspooler(p->mem_ctx,
7888                          get_session_info_system(),
7889                          p->msg_ctx,
7890                          0,
7891                          info2,
7892                          NULL);
7893
7894         err = winreg_update_printer(p->mem_ctx,
7895                                     get_session_info_system(),
7896                                     p->msg_ctx,
7897                                     info2->sharename,
7898                                     info2_mask,
7899                                     info2,
7900                                     devmode,
7901                                     secdesc);
7902         if (!W_ERROR_IS_OK(err)) {
7903                 return err;
7904         }
7905
7906         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7907         if (!W_ERROR_IS_OK(err)) {
7908                 /* Handle open failed - remove addition. */
7909                 ZERO_STRUCTP(handle);
7910                 return err;
7911         }
7912
7913         return WERR_OK;
7914 }
7915
7916 /****************************************************************
7917  _spoolss_AddPrinterEx
7918 ****************************************************************/
7919
7920 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7921                              struct spoolss_AddPrinterEx *r)
7922 {
7923         switch (r->in.info_ctr->level) {
7924         case 1:
7925                 /* we don't handle yet */
7926                 /* but I know what to do ... */
7927                 return WERR_UNKNOWN_LEVEL;
7928         case 2:
7929                 return spoolss_addprinterex_level_2(p, r->in.server,
7930                                                     r->in.info_ctr,
7931                                                     r->in.devmode_ctr->devmode,
7932                                                     r->in.secdesc_ctr->sd,
7933                                                     r->in.userlevel_ctr,
7934                                                     r->out.handle);
7935         default:
7936                 return WERR_UNKNOWN_LEVEL;
7937         }
7938 }
7939
7940 /****************************************************************
7941  _spoolss_AddPrinter
7942 ****************************************************************/
7943
7944 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7945                            struct spoolss_AddPrinter *r)
7946 {
7947         struct spoolss_AddPrinterEx a;
7948         struct spoolss_UserLevelCtr userlevel_ctr;
7949
7950         ZERO_STRUCT(userlevel_ctr);
7951
7952         userlevel_ctr.level = 1;
7953
7954         a.in.server             = r->in.server;
7955         a.in.info_ctr           = r->in.info_ctr;
7956         a.in.devmode_ctr        = r->in.devmode_ctr;
7957         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7958         a.in.userlevel_ctr      = &userlevel_ctr;
7959         a.out.handle            = r->out.handle;
7960
7961         return _spoolss_AddPrinterEx(p, &a);
7962 }
7963
7964 /****************************************************************
7965  _spoolss_AddPrinterDriverEx
7966 ****************************************************************/
7967
7968 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7969                                    struct spoolss_AddPrinterDriverEx *r)
7970 {
7971         WERROR err = WERR_OK;
7972         const char *driver_name = NULL;
7973         uint32_t version;
7974         const char *fn;
7975
7976         switch (p->opnum) {
7977                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7978                         fn = "_spoolss_AddPrinterDriver";
7979                         break;
7980                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7981                         fn = "_spoolss_AddPrinterDriverEx";
7982                         break;
7983                 default:
7984                         return WERR_INVALID_PARAM;
7985         }
7986
7987         /*
7988          * we only support the semantics of AddPrinterDriver()
7989          * i.e. only copy files that are newer than existing ones
7990          */
7991
7992         if (r->in.flags == 0) {
7993                 return WERR_INVALID_PARAM;
7994         }
7995
7996         if (r->in.flags != APD_COPY_NEW_FILES) {
7997                 return WERR_ACCESS_DENIED;
7998         }
7999
8000         /* FIXME */
8001         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8002                 /* Clever hack from Martin Zielinski <mz@seh.de>
8003                  * to allow downgrade from level 8 (Vista).
8004                  */
8005                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8006                         r->in.info_ctr->level));
8007                 return WERR_UNKNOWN_LEVEL;
8008         }
8009
8010         DEBUG(5,("Cleaning driver's information\n"));
8011         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8012         if (!W_ERROR_IS_OK(err))
8013                 goto done;
8014
8015         DEBUG(5,("Moving driver to final destination\n"));
8016         err = move_driver_to_download_area(p, r->in.info_ctr);
8017         if (!W_ERROR_IS_OK(err)) {
8018                 goto done;
8019         }
8020
8021         err = winreg_add_driver(p->mem_ctx,
8022                                 get_session_info_system(),
8023                                 p->msg_ctx,
8024                                 r->in.info_ctr,
8025                                 &driver_name,
8026                                 &version);
8027         if (!W_ERROR_IS_OK(err)) {
8028                 goto done;
8029         }
8030
8031         /*
8032          * I think this is where he DrvUpgradePrinter() hook would be
8033          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8034          * server.  Right now, we just need to send ourselves a message
8035          * to update each printer bound to this driver.   --jerry
8036          */
8037
8038         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8039                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8040                         fn, driver_name));
8041         }
8042
8043 done:
8044         return err;
8045 }
8046
8047 /****************************************************************
8048  _spoolss_AddPrinterDriver
8049 ****************************************************************/
8050
8051 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8052                                  struct spoolss_AddPrinterDriver *r)
8053 {
8054         struct spoolss_AddPrinterDriverEx a;
8055
8056         switch (r->in.info_ctr->level) {
8057         case 2:
8058         case 3:
8059         case 4:
8060         case 5:
8061                 break;
8062         default:
8063                 return WERR_UNKNOWN_LEVEL;
8064         }
8065
8066         a.in.servername         = r->in.servername;
8067         a.in.info_ctr           = r->in.info_ctr;
8068         a.in.flags              = APD_COPY_NEW_FILES;
8069
8070         return _spoolss_AddPrinterDriverEx(p, &a);
8071 }
8072
8073 /****************************************************************************
8074 ****************************************************************************/
8075
8076 struct _spoolss_paths {
8077         int type;
8078         const char *share;
8079         const char *dir;
8080 };
8081
8082 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8083
8084 static const struct _spoolss_paths spoolss_paths[]= {
8085         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8086         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8087 };
8088
8089 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8090                                           const char *servername,
8091                                           const char *environment,
8092                                           int component,
8093                                           char **path)
8094 {
8095         const char *pservername = NULL;
8096         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8097         const char *short_archi;
8098
8099         *path = NULL;
8100
8101         /* environment may be empty */
8102         if (environment && strlen(environment)) {
8103                 long_archi = environment;
8104         }
8105
8106         /* servername may be empty */
8107         if (servername && strlen(servername)) {
8108                 pservername = canon_servername(servername);
8109
8110                 if (!is_myname_or_ipaddr(pservername)) {
8111                         return WERR_INVALID_PARAM;
8112                 }
8113         }
8114
8115         if (!(short_archi = get_short_archi(long_archi))) {
8116                 return WERR_INVALID_ENVIRONMENT;
8117         }
8118
8119         switch (component) {
8120         case SPOOLSS_PRTPROCS_PATH:
8121         case SPOOLSS_DRIVER_PATH:
8122                 if (pservername) {
8123                         *path = talloc_asprintf(mem_ctx,
8124                                         "\\\\%s\\%s\\%s",
8125                                         pservername,
8126                                         spoolss_paths[component].share,
8127                                         short_archi);
8128                 } else {
8129                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8130                                         SPOOLSS_DEFAULT_SERVER_PATH,
8131                                         spoolss_paths[component].dir,
8132                                         short_archi);
8133                 }
8134                 break;
8135         default:
8136                 return WERR_INVALID_PARAM;
8137         }
8138
8139         if (!*path) {
8140                 return WERR_NOMEM;
8141         }
8142
8143         return WERR_OK;
8144 }
8145
8146 /****************************************************************************
8147 ****************************************************************************/
8148
8149 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8150                                           const char *servername,
8151                                           const char *environment,
8152                                           struct spoolss_DriverDirectoryInfo1 *r)
8153 {
8154         WERROR werr;
8155         char *path = NULL;
8156
8157         werr = compose_spoolss_server_path(mem_ctx,
8158                                            servername,
8159                                            environment,
8160                                            SPOOLSS_DRIVER_PATH,
8161                                            &path);
8162         if (!W_ERROR_IS_OK(werr)) {
8163                 return werr;
8164         }
8165
8166         DEBUG(4,("printer driver directory: [%s]\n", path));
8167
8168         r->directory_name = path;
8169
8170         return WERR_OK;
8171 }
8172
8173 /****************************************************************
8174  _spoolss_GetPrinterDriverDirectory
8175 ****************************************************************/
8176
8177 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8178                                           struct spoolss_GetPrinterDriverDirectory *r)
8179 {
8180         WERROR werror;
8181
8182         /* that's an [in out] buffer */
8183
8184         if (!r->in.buffer && (r->in.offered != 0)) {
8185                 return WERR_INVALID_PARAM;
8186         }
8187
8188         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8189                 r->in.level));
8190
8191         *r->out.needed = 0;
8192
8193         /* r->in.level is ignored */
8194
8195         werror = getprinterdriverdir_level_1(p->mem_ctx,
8196                                              r->in.server,
8197                                              r->in.environment,
8198                                              &r->out.info->info1);
8199         if (!W_ERROR_IS_OK(werror)) {
8200                 TALLOC_FREE(r->out.info);
8201                 return werror;
8202         }
8203
8204         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8205                                                r->out.info, r->in.level);
8206         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8207
8208         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8209 }
8210
8211 /****************************************************************
8212  _spoolss_EnumPrinterData
8213 ****************************************************************/
8214
8215 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8216                                 struct spoolss_EnumPrinterData *r)
8217 {
8218         WERROR result;
8219         struct spoolss_EnumPrinterDataEx r2;
8220         uint32_t count;
8221         struct spoolss_PrinterEnumValues *info, *val = NULL;
8222         uint32_t needed;
8223
8224         r2.in.handle    = r->in.handle;
8225         r2.in.key_name  = "PrinterDriverData";
8226         r2.in.offered   = 0;
8227         r2.out.count    = &count;
8228         r2.out.info     = &info;
8229         r2.out.needed   = &needed;
8230
8231         result = _spoolss_EnumPrinterDataEx(p, &r2);
8232         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8233                 r2.in.offered = needed;
8234                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8235         }
8236         if (!W_ERROR_IS_OK(result)) {
8237                 return result;
8238         }
8239
8240         /*
8241          * The NT machine wants to know the biggest size of value and data
8242          *
8243          * cf: MSDN EnumPrinterData remark section
8244          */
8245
8246         if (!r->in.value_offered && !r->in.data_offered) {
8247                 uint32_t biggest_valuesize = 0;
8248                 uint32_t biggest_datasize = 0;
8249                 int i, name_length;
8250
8251                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8252
8253                 for (i=0; i<count; i++) {
8254
8255                         name_length = strlen(info[i].value_name);
8256                         if (strlen(info[i].value_name) > biggest_valuesize) {
8257                                 biggest_valuesize = name_length;
8258                         }
8259
8260                         if (info[i].data_length > biggest_datasize) {
8261                                 biggest_datasize = info[i].data_length;
8262                         }
8263
8264                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8265                                 biggest_datasize));
8266                 }
8267
8268                 /* the value is an UNICODE string but real_value_size is the length
8269                    in bytes including the trailing 0 */
8270
8271                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8272                 *r->out.data_needed  = biggest_datasize;
8273
8274                 DEBUG(6,("final values: [%d], [%d]\n",
8275                         *r->out.value_needed, *r->out.data_needed));
8276
8277                 return WERR_OK;
8278         }
8279
8280         if (r->in.enum_index < count) {
8281                 val = &info[r->in.enum_index];
8282         }
8283
8284         if (val == NULL) {
8285                 /* out_value should default to "" or else NT4 has
8286                    problems unmarshalling the response */
8287
8288                 if (r->in.value_offered) {
8289                         *r->out.value_needed = 1;
8290                         r->out.value_name = talloc_strdup(r, "");
8291                         if (!r->out.value_name) {
8292                                 return WERR_NOMEM;
8293                         }
8294                 } else {
8295                         r->out.value_name = NULL;
8296                         *r->out.value_needed = 0;
8297                 }
8298
8299                 /* the data is counted in bytes */
8300
8301                 *r->out.data_needed = r->in.data_offered;
8302
8303                 result = WERR_NO_MORE_ITEMS;
8304         } else {
8305                 /*
8306                  * the value is:
8307                  * - counted in bytes in the request
8308                  * - counted in UNICODE chars in the max reply
8309                  * - counted in bytes in the real size
8310                  *
8311                  * take a pause *before* coding not *during* coding
8312                  */
8313
8314                 /* name */
8315                 if (r->in.value_offered) {
8316                         r->out.value_name = talloc_strdup(r, val->value_name);
8317                         if (!r->out.value_name) {
8318                                 return WERR_NOMEM;
8319                         }
8320                         *r->out.value_needed = val->value_name_len;
8321                 } else {
8322                         r->out.value_name = NULL;
8323                         *r->out.value_needed = 0;
8324                 }
8325
8326                 /* type */
8327
8328                 *r->out.type = val->type;
8329
8330                 /* data - counted in bytes */
8331
8332                 /*
8333                  * See the section "Dynamically Typed Query Parameters"
8334                  * in MS-RPRN.
8335                  */
8336
8337                 if (r->out.data && val->data && val->data->data &&
8338                                 val->data_length && r->in.data_offered) {
8339                         memcpy(r->out.data, val->data->data,
8340                                 MIN(val->data_length,r->in.data_offered));
8341                 }
8342
8343                 *r->out.data_needed = val->data_length;
8344
8345                 result = WERR_OK;
8346         }
8347
8348         return result;
8349 }
8350
8351 /****************************************************************
8352  _spoolss_SetPrinterData
8353 ****************************************************************/
8354
8355 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8356                                struct spoolss_SetPrinterData *r)
8357 {
8358         struct spoolss_SetPrinterDataEx r2;
8359
8360         r2.in.handle            = r->in.handle;
8361         r2.in.key_name          = "PrinterDriverData";
8362         r2.in.value_name        = r->in.value_name;
8363         r2.in.type              = r->in.type;
8364         r2.in.data              = r->in.data;
8365         r2.in.offered           = r->in.offered;
8366
8367         return _spoolss_SetPrinterDataEx(p, &r2);
8368 }
8369
8370 /****************************************************************
8371  _spoolss_ResetPrinter
8372 ****************************************************************/
8373
8374 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8375                              struct spoolss_ResetPrinter *r)
8376 {
8377         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8378         int             snum;
8379
8380         DEBUG(5,("_spoolss_ResetPrinter\n"));
8381
8382         /*
8383          * All we do is to check to see if the handle and queue is valid.
8384          * This call really doesn't mean anything to us because we only
8385          * support RAW printing.   --jerry
8386          */
8387
8388         if (!Printer) {
8389                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8390                         OUR_HANDLE(r->in.handle)));
8391                 return WERR_BADFID;
8392         }
8393
8394         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8395                 return WERR_BADFID;
8396
8397
8398         /* blindly return success */
8399         return WERR_OK;
8400 }
8401
8402 /****************************************************************
8403  _spoolss_DeletePrinterData
8404 ****************************************************************/
8405
8406 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8407                                   struct spoolss_DeletePrinterData *r)
8408 {
8409         struct spoolss_DeletePrinterDataEx r2;
8410
8411         r2.in.handle            = r->in.handle;
8412         r2.in.key_name          = "PrinterDriverData";
8413         r2.in.value_name        = r->in.value_name;
8414
8415         return _spoolss_DeletePrinterDataEx(p, &r2);
8416 }
8417
8418 /****************************************************************
8419  _spoolss_AddForm
8420 ****************************************************************/
8421
8422 WERROR _spoolss_AddForm(struct pipes_struct *p,
8423                         struct spoolss_AddForm *r)
8424 {
8425         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8426         int snum = -1;
8427         WERROR status = WERR_OK;
8428
8429         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8430
8431         DEBUG(5,("_spoolss_AddForm\n"));
8432
8433         if (!Printer) {
8434                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8435                         OUR_HANDLE(r->in.handle)));
8436                 return WERR_BADFID;
8437         }
8438
8439         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8440            and not a printer admin, then fail */
8441
8442         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8443             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8444             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8445                                           p->session_info->info3->base.domain.string,
8446                                           NULL,
8447                                           p->session_info->security_token,
8448                                           lp_printer_admin(snum))) {
8449                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8450                 return WERR_ACCESS_DENIED;
8451         }
8452
8453         switch (form->flags) {
8454         case SPOOLSS_FORM_USER:
8455         case SPOOLSS_FORM_BUILTIN:
8456         case SPOOLSS_FORM_PRINTER:
8457                 break;
8458         default:
8459                 return WERR_INVALID_PARAM;
8460         }
8461
8462         status = winreg_printer_addform1(p->mem_ctx,
8463                                          get_session_info_system(),
8464                                          p->msg_ctx,
8465                                          form);
8466         if (!W_ERROR_IS_OK(status)) {
8467                 return status;
8468         }
8469
8470         /*
8471          * ChangeID must always be set if this is a printer
8472          */
8473         if (Printer->printer_type == SPLHND_PRINTER) {
8474                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8475                         return WERR_BADFID;
8476                 }
8477
8478                 status = winreg_printer_update_changeid(p->mem_ctx,
8479                                                         get_session_info_system(),
8480                                                         p->msg_ctx,
8481                                                         lp_const_servicename(snum));
8482                 if (!W_ERROR_IS_OK(status)) {
8483                         return status;
8484                 }
8485         }
8486
8487         return status;
8488 }
8489
8490 /****************************************************************
8491  _spoolss_DeleteForm
8492 ****************************************************************/
8493
8494 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8495                            struct spoolss_DeleteForm *r)
8496 {
8497         const char *form_name = r->in.form_name;
8498         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8499         int snum = -1;
8500         WERROR status = WERR_OK;
8501
8502         DEBUG(5,("_spoolss_DeleteForm\n"));
8503
8504         if (!Printer) {
8505                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8506                         OUR_HANDLE(r->in.handle)));
8507                 return WERR_BADFID;
8508         }
8509
8510         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8511             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8512             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8513                                           p->session_info->info3->base.domain.string,
8514                                           NULL,
8515                                           p->session_info->security_token,
8516                                           lp_printer_admin(snum))) {
8517                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8518                 return WERR_ACCESS_DENIED;
8519         }
8520
8521         status = winreg_printer_deleteform1(p->mem_ctx,
8522                                             get_session_info_system(),
8523                                             p->msg_ctx,
8524                                             form_name);
8525         if (!W_ERROR_IS_OK(status)) {
8526                 return status;
8527         }
8528
8529         /*
8530          * ChangeID must always be set if this is a printer
8531          */
8532         if (Printer->printer_type == SPLHND_PRINTER) {
8533                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8534                         return WERR_BADFID;
8535                 }
8536
8537                 status = winreg_printer_update_changeid(p->mem_ctx,
8538                                                         get_session_info_system(),
8539                                                         p->msg_ctx,
8540                                                         lp_const_servicename(snum));
8541                 if (!W_ERROR_IS_OK(status)) {
8542                         return status;
8543                 }
8544         }
8545
8546         return status;
8547 }
8548
8549 /****************************************************************
8550  _spoolss_SetForm
8551 ****************************************************************/
8552
8553 WERROR _spoolss_SetForm(struct pipes_struct *p,
8554                         struct spoolss_SetForm *r)
8555 {
8556         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8557         const char *form_name = r->in.form_name;
8558         int snum = -1;
8559         WERROR status = WERR_OK;
8560
8561         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8562
8563         DEBUG(5,("_spoolss_SetForm\n"));
8564
8565         if (!Printer) {
8566                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8567                         OUR_HANDLE(r->in.handle)));
8568                 return WERR_BADFID;
8569         }
8570
8571         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8572            and not a printer admin, then fail */
8573
8574         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8575              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8576              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8577                                           p->session_info->info3->base.domain.string,
8578                                           NULL,
8579                                           p->session_info->security_token,
8580                                           lp_printer_admin(snum))) {
8581                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8582                 return WERR_ACCESS_DENIED;
8583         }
8584
8585         status = winreg_printer_setform1(p->mem_ctx,
8586                                          get_session_info_system(),
8587                                          p->msg_ctx,
8588                                          form_name,
8589                                          form);
8590         if (!W_ERROR_IS_OK(status)) {
8591                 return status;
8592         }
8593
8594         /*
8595          * ChangeID must always be set if this is a printer
8596          */
8597         if (Printer->printer_type == SPLHND_PRINTER) {
8598                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8599                         return WERR_BADFID;
8600                 }
8601
8602                 status = winreg_printer_update_changeid(p->mem_ctx,
8603                                                         get_session_info_system(),
8604                                                         p->msg_ctx,
8605                                                         lp_const_servicename(snum));
8606                 if (!W_ERROR_IS_OK(status)) {
8607                         return status;
8608                 }
8609         }
8610
8611         return status;
8612 }
8613
8614 /****************************************************************************
8615  fill_print_processor1
8616 ****************************************************************************/
8617
8618 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8619                                     struct spoolss_PrintProcessorInfo1 *r,
8620                                     const char *print_processor_name)
8621 {
8622         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8623         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8624
8625         return WERR_OK;
8626 }
8627
8628 /****************************************************************************
8629  enumprintprocessors level 1.
8630 ****************************************************************************/
8631
8632 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8633                                           union spoolss_PrintProcessorInfo **info_p,
8634                                           uint32_t *count)
8635 {
8636         union spoolss_PrintProcessorInfo *info;
8637         WERROR result;
8638
8639         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8640         W_ERROR_HAVE_NO_MEMORY(info);
8641
8642         *count = 1;
8643
8644         result = fill_print_processor1(info, &info[0].info1, "winprint");
8645         if (!W_ERROR_IS_OK(result)) {
8646                 goto out;
8647         }
8648
8649  out:
8650         if (!W_ERROR_IS_OK(result)) {
8651                 TALLOC_FREE(info);
8652                 *count = 0;
8653                 return result;
8654         }
8655
8656         *info_p = info;
8657
8658         return WERR_OK;
8659 }
8660
8661 /****************************************************************
8662  _spoolss_EnumPrintProcessors
8663 ****************************************************************/
8664
8665 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8666                                     struct spoolss_EnumPrintProcessors *r)
8667 {
8668         WERROR result;
8669
8670         /* that's an [in out] buffer */
8671
8672         if (!r->in.buffer && (r->in.offered != 0)) {
8673                 return WERR_INVALID_PARAM;
8674         }
8675
8676         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8677
8678         /*
8679          * Enumerate the print processors ...
8680          *
8681          * Just reply with "winprint", to keep NT happy
8682          * and I can use my nice printer checker.
8683          */
8684
8685         *r->out.count = 0;
8686         *r->out.needed = 0;
8687         *r->out.info = NULL;
8688
8689         if (!get_short_archi(r->in.environment)) {
8690                 return WERR_INVALID_ENVIRONMENT;
8691         }
8692
8693         switch (r->in.level) {
8694         case 1:
8695                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8696                                                      r->out.count);
8697                 break;
8698         default:
8699                 return WERR_UNKNOWN_LEVEL;
8700         }
8701
8702         if (!W_ERROR_IS_OK(result)) {
8703                 return result;
8704         }
8705
8706         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8707                                                      spoolss_EnumPrintProcessors,
8708                                                      *r->out.info, r->in.level,
8709                                                      *r->out.count);
8710         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8711         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8712
8713         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8714 }
8715
8716 /****************************************************************************
8717  fill_printprocdatatype1
8718 ****************************************************************************/
8719
8720 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8721                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8722                                       const char *name_array)
8723 {
8724         r->name_array = talloc_strdup(mem_ctx, name_array);
8725         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8726
8727         return WERR_OK;
8728 }
8729
8730 /****************************************************************************
8731  enumprintprocdatatypes level 1.
8732 ****************************************************************************/
8733
8734 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8735                                              union spoolss_PrintProcDataTypesInfo **info_p,
8736                                              uint32_t *count)
8737 {
8738         WERROR result;
8739         union spoolss_PrintProcDataTypesInfo *info;
8740
8741         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8742         W_ERROR_HAVE_NO_MEMORY(info);
8743
8744         *count = 1;
8745
8746         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8747         if (!W_ERROR_IS_OK(result)) {
8748                 goto out;
8749         }
8750
8751  out:
8752         if (!W_ERROR_IS_OK(result)) {
8753                 TALLOC_FREE(info);
8754                 *count = 0;
8755                 return result;
8756         }
8757
8758         *info_p = info;
8759
8760         return WERR_OK;
8761 }
8762
8763 /****************************************************************
8764  _spoolss_EnumPrintProcDataTypes
8765 ****************************************************************/
8766
8767 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8768                                        struct spoolss_EnumPrintProcDataTypes *r)
8769 {
8770         WERROR result;
8771
8772         /* that's an [in out] buffer */
8773
8774         if (!r->in.buffer && (r->in.offered != 0)) {
8775                 return WERR_INVALID_PARAM;
8776         }
8777
8778         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8779
8780         *r->out.count = 0;
8781         *r->out.needed = 0;
8782         *r->out.info = NULL;
8783
8784         if (r->in.print_processor_name == NULL ||
8785             !strequal(r->in.print_processor_name, "winprint")) {
8786                 return WERR_UNKNOWN_PRINTPROCESSOR;
8787         }
8788
8789         switch (r->in.level) {
8790         case 1:
8791                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8792                                                         r->out.count);
8793                 break;
8794         default:
8795                 return WERR_UNKNOWN_LEVEL;
8796         }
8797
8798         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8799                                                      spoolss_EnumPrintProcDataTypes,
8800                                                      *r->out.info, r->in.level,
8801                                                      *r->out.count);
8802         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8803         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8804
8805         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8806 }
8807
8808 /****************************************************************************
8809  fill_monitor_1
8810 ****************************************************************************/
8811
8812 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8813                              struct spoolss_MonitorInfo1 *r,
8814                              const char *monitor_name)
8815 {
8816         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8817         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8818
8819         return WERR_OK;
8820 }
8821
8822 /****************************************************************************
8823  fill_monitor_2
8824 ****************************************************************************/
8825
8826 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8827                              struct spoolss_MonitorInfo2 *r,
8828                              const char *monitor_name,
8829                              const char *environment,
8830                              const char *dll_name)
8831 {
8832         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8833         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8834         r->environment                  = talloc_strdup(mem_ctx, environment);
8835         W_ERROR_HAVE_NO_MEMORY(r->environment);
8836         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8837         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8838
8839         return WERR_OK;
8840 }
8841
8842 /****************************************************************************
8843  enumprintmonitors level 1.
8844 ****************************************************************************/
8845
8846 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8847                                         union spoolss_MonitorInfo **info_p,
8848                                         uint32_t *count)
8849 {
8850         union spoolss_MonitorInfo *info;
8851         WERROR result = WERR_OK;
8852
8853         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8854         W_ERROR_HAVE_NO_MEMORY(info);
8855
8856         *count = 2;
8857
8858         result = fill_monitor_1(info, &info[0].info1,
8859                                 SPL_LOCAL_PORT);
8860         if (!W_ERROR_IS_OK(result)) {
8861                 goto out;
8862         }
8863
8864         result = fill_monitor_1(info, &info[1].info1,
8865                                 SPL_TCPIP_PORT);
8866         if (!W_ERROR_IS_OK(result)) {
8867                 goto out;
8868         }
8869
8870 out:
8871         if (!W_ERROR_IS_OK(result)) {
8872                 TALLOC_FREE(info);
8873                 *count = 0;
8874                 return result;
8875         }
8876
8877         *info_p = info;
8878
8879         return WERR_OK;
8880 }
8881
8882 /****************************************************************************
8883  enumprintmonitors level 2.
8884 ****************************************************************************/
8885
8886 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8887                                         union spoolss_MonitorInfo **info_p,
8888                                         uint32_t *count)
8889 {
8890         union spoolss_MonitorInfo *info;
8891         WERROR result = WERR_OK;
8892
8893         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8894         W_ERROR_HAVE_NO_MEMORY(info);
8895
8896         *count = 2;
8897
8898         result = fill_monitor_2(info, &info[0].info2,
8899                                 SPL_LOCAL_PORT,
8900                                 "Windows NT X86", /* FIXME */
8901                                 "localmon.dll");
8902         if (!W_ERROR_IS_OK(result)) {
8903                 goto out;
8904         }
8905
8906         result = fill_monitor_2(info, &info[1].info2,
8907                                 SPL_TCPIP_PORT,
8908                                 "Windows NT X86", /* FIXME */
8909                                 "tcpmon.dll");
8910         if (!W_ERROR_IS_OK(result)) {
8911                 goto out;
8912         }
8913
8914 out:
8915         if (!W_ERROR_IS_OK(result)) {
8916                 TALLOC_FREE(info);
8917                 *count = 0;
8918                 return result;
8919         }
8920
8921         *info_p = info;
8922
8923         return WERR_OK;
8924 }
8925
8926 /****************************************************************
8927  _spoolss_EnumMonitors
8928 ****************************************************************/
8929
8930 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8931                              struct spoolss_EnumMonitors *r)
8932 {
8933         WERROR result;
8934
8935         /* that's an [in out] buffer */
8936
8937         if (!r->in.buffer && (r->in.offered != 0)) {
8938                 return WERR_INVALID_PARAM;
8939         }
8940
8941         DEBUG(5,("_spoolss_EnumMonitors\n"));
8942
8943         /*
8944          * Enumerate the print monitors ...
8945          *
8946          * Just reply with "Local Port", to keep NT happy
8947          * and I can use my nice printer checker.
8948          */
8949
8950         *r->out.count = 0;
8951         *r->out.needed = 0;
8952         *r->out.info = NULL;
8953
8954         switch (r->in.level) {
8955         case 1:
8956                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8957                                                    r->out.count);
8958                 break;
8959         case 2:
8960                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8961                                                    r->out.count);
8962                 break;
8963         default:
8964                 return WERR_UNKNOWN_LEVEL;
8965         }
8966
8967         if (!W_ERROR_IS_OK(result)) {
8968                 return result;
8969         }
8970
8971         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8972                                                      spoolss_EnumMonitors,
8973                                                      *r->out.info, r->in.level,
8974                                                      *r->out.count);
8975         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8976         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8977
8978         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8979 }
8980
8981 /****************************************************************************
8982 ****************************************************************************/
8983
8984 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8985                              const print_queue_struct *queue,
8986                              int count, int snum,
8987                              struct spoolss_PrinterInfo2 *pinfo2,
8988                              uint32_t jobid,
8989                              struct spoolss_JobInfo1 *r)
8990 {
8991         int i = 0;
8992         bool found = false;
8993
8994         for (i=0; i<count; i++) {
8995                 if (queue[i].job == (int)jobid) {
8996                         found = true;
8997                         break;
8998                 }
8999         }
9000
9001         if (found == false) {
9002                 /* NT treats not found as bad param... yet another bad choice */
9003                 return WERR_INVALID_PARAM;
9004         }
9005
9006         return fill_job_info1(mem_ctx,
9007                               r,
9008                               &queue[i],
9009                               i,
9010                               snum,
9011                               pinfo2);
9012 }
9013
9014 /****************************************************************************
9015 ****************************************************************************/
9016
9017 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9018                              const print_queue_struct *queue,
9019                              int count, int snum,
9020                              struct spoolss_PrinterInfo2 *pinfo2,
9021                              uint32_t jobid,
9022                              struct spoolss_JobInfo2 *r)
9023 {
9024         int i = 0;
9025         bool found = false;
9026         struct spoolss_DeviceMode *devmode;
9027         WERROR result;
9028
9029         for (i=0; i<count; i++) {
9030                 if (queue[i].job == (int)jobid) {
9031                         found = true;
9032                         break;
9033                 }
9034         }
9035
9036         if (found == false) {
9037                 /* NT treats not found as bad param... yet another bad
9038                    choice */
9039                 return WERR_INVALID_PARAM;
9040         }
9041
9042         /*
9043          * if the print job does not have a DEVMODE associated with it,
9044          * just use the one for the printer. A NULL devicemode is not
9045          *  a failure condition
9046          */
9047
9048         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9049         if (!devmode) {
9050                 result = spoolss_create_default_devmode(mem_ctx,
9051                                                 pinfo2->printername,
9052                                                 &devmode);
9053                 if (!W_ERROR_IS_OK(result)) {
9054                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9055                         return result;
9056                 }
9057         }
9058
9059         return fill_job_info2(mem_ctx,
9060                               r,
9061                               &queue[i],
9062                               i,
9063                               snum,
9064                               pinfo2,
9065                               devmode);
9066 }
9067
9068 /****************************************************************
9069  _spoolss_GetJob
9070 ****************************************************************/
9071
9072 WERROR _spoolss_GetJob(struct pipes_struct *p,
9073                        struct spoolss_GetJob *r)
9074 {
9075         WERROR result = WERR_OK;
9076         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9077         int snum;
9078         int count;
9079         print_queue_struct      *queue = NULL;
9080         print_status_struct prt_status;
9081
9082         /* that's an [in out] buffer */
9083
9084         if (!r->in.buffer && (r->in.offered != 0)) {
9085                 return WERR_INVALID_PARAM;
9086         }
9087
9088         DEBUG(5,("_spoolss_GetJob\n"));
9089
9090         *r->out.needed = 0;
9091
9092         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9093                 return WERR_BADFID;
9094         }
9095
9096         result = winreg_get_printer(p->mem_ctx,
9097                                     get_session_info_system(),
9098                                     p->msg_ctx,
9099                                     lp_const_servicename(snum),
9100                                     &pinfo2);
9101         if (!W_ERROR_IS_OK(result)) {
9102                 return result;
9103         }
9104
9105         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9106
9107         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9108                      count, prt_status.status, prt_status.message));
9109
9110         switch (r->in.level) {
9111         case 1:
9112                 result = getjob_level_1(p->mem_ctx,
9113                                         queue, count, snum, pinfo2,
9114                                         r->in.job_id, &r->out.info->info1);
9115                 break;
9116         case 2:
9117                 result = getjob_level_2(p->mem_ctx,
9118                                         queue, count, snum, pinfo2,
9119                                         r->in.job_id, &r->out.info->info2);
9120                 break;
9121         default:
9122                 result = WERR_UNKNOWN_LEVEL;
9123                 break;
9124         }
9125
9126         SAFE_FREE(queue);
9127         TALLOC_FREE(pinfo2);
9128
9129         if (!W_ERROR_IS_OK(result)) {
9130                 TALLOC_FREE(r->out.info);
9131                 return result;
9132         }
9133
9134         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9135                                                                                    r->in.level);
9136         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9137
9138         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9139 }
9140
9141 /****************************************************************
9142  _spoolss_GetPrinterDataEx
9143 ****************************************************************/
9144
9145 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9146                                  struct spoolss_GetPrinterDataEx *r)
9147 {
9148
9149         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9150         const char *printer;
9151         int                     snum = 0;
9152         WERROR result = WERR_OK;
9153         DATA_BLOB blob;
9154         enum winreg_Type val_type;
9155         uint8_t *val_data;
9156         uint32_t val_size;
9157
9158
9159         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9160
9161         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9162                 r->in.key_name, r->in.value_name));
9163
9164         /* in case of problem, return some default values */
9165
9166         *r->out.needed  = 0;
9167         *r->out.type    = REG_NONE;
9168
9169         if (!Printer) {
9170                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9171                         OUR_HANDLE(r->in.handle)));
9172                 result = WERR_BADFID;
9173                 goto done;
9174         }
9175
9176         /* Is the handle to a printer or to the server? */
9177
9178         if (Printer->printer_type == SPLHND_SERVER) {
9179
9180                 union spoolss_PrinterData data;
9181
9182                 result = getprinterdata_printer_server(p->mem_ctx,
9183                                                        r->in.value_name,
9184                                                        r->out.type,
9185                                                        &data);
9186                 if (!W_ERROR_IS_OK(result)) {
9187                         return result;
9188                 }
9189
9190                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9191                                                   *r->out.type, &data);
9192                 if (!W_ERROR_IS_OK(result)) {
9193                         return result;
9194                 }
9195
9196                 *r->out.needed = blob.length;
9197
9198                 if (r->in.offered >= *r->out.needed) {
9199                         memcpy(r->out.data, blob.data, blob.length);
9200                 }
9201
9202                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9203         }
9204
9205         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9206                 return WERR_BADFID;
9207         }
9208         printer = lp_const_servicename(snum);
9209
9210         /* check to see if the keyname is valid */
9211         if (!strlen(r->in.key_name)) {
9212                 return WERR_INVALID_PARAM;
9213         }
9214
9215         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9216         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9217             strequal(r->in.value_name, "ChangeId")) {
9218                 *r->out.type = REG_DWORD;
9219                 *r->out.needed = 4;
9220                 if (r->in.offered >= *r->out.needed) {
9221                         uint32_t changeid = 0;
9222
9223                         result = winreg_printer_get_changeid(p->mem_ctx,
9224                                                              get_session_info_system(),
9225                                                              p->msg_ctx,
9226                                                              printer,
9227                                                              &changeid);
9228                         if (!W_ERROR_IS_OK(result)) {
9229                                 return result;
9230                         }
9231
9232                         SIVAL(r->out.data, 0, changeid);
9233                         result = WERR_OK;
9234                 }
9235                 goto done;
9236         }
9237
9238         result = winreg_get_printer_dataex(p->mem_ctx,
9239                                            get_session_info_system(),
9240                                            p->msg_ctx,
9241                                            printer,
9242                                            r->in.key_name,
9243                                            r->in.value_name,
9244                                            &val_type,
9245                                            &val_data,
9246                                            &val_size);
9247         if (!W_ERROR_IS_OK(result)) {
9248                 return result;
9249         }
9250
9251         *r->out.needed = val_size;
9252         *r->out.type = val_type;
9253
9254         if (r->in.offered >= *r->out.needed) {
9255                 memcpy(r->out.data, val_data, val_size);
9256         }
9257
9258  done:
9259         /* retain type when returning WERR_MORE_DATA */
9260         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9261
9262         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9263 }
9264
9265 /****************************************************************
9266  _spoolss_SetPrinterDataEx
9267 ****************************************************************/
9268
9269 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9270                                  struct spoolss_SetPrinterDataEx *r)
9271 {
9272         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9273         int                     snum = 0;
9274         WERROR                  result = WERR_OK;
9275         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9276         char                    *oid_string;
9277
9278         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9279
9280         /* From MSDN documentation of SetPrinterDataEx: pass request to
9281            SetPrinterData if key is "PrinterDriverData" */
9282
9283         if (!Printer) {
9284                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9285                         OUR_HANDLE(r->in.handle)));
9286                 return WERR_BADFID;
9287         }
9288
9289         if (Printer->printer_type == SPLHND_SERVER) {
9290                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9291                         "Not implemented for server handles yet\n"));
9292                 return WERR_INVALID_PARAM;
9293         }
9294
9295         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9296                 return WERR_BADFID;
9297         }
9298
9299         /*
9300          * Access check : NT returns "access denied" if you make a
9301          * SetPrinterData call without the necessary privildge.
9302          * we were originally returning OK if nothing changed
9303          * which made Win2k issue **a lot** of SetPrinterData
9304          * when connecting to a printer  --jerry
9305          */
9306
9307         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9308                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9309                         "change denied by handle access permissions\n"));
9310                 return WERR_ACCESS_DENIED;
9311         }
9312
9313         result = winreg_get_printer(Printer,
9314                                     get_session_info_system(),
9315                                     p->msg_ctx,
9316                                     lp_servicename(snum),
9317                                     &pinfo2);
9318         if (!W_ERROR_IS_OK(result)) {
9319                 return result;
9320         }
9321
9322         /* check for OID in valuename */
9323
9324         oid_string = strchr(r->in.value_name, ',');
9325         if (oid_string) {
9326                 *oid_string = '\0';
9327                 oid_string++;
9328         }
9329
9330         /* save the registry data */
9331
9332         result = winreg_set_printer_dataex(p->mem_ctx,
9333                                            get_session_info_system(),
9334                                            p->msg_ctx,
9335                                            pinfo2->sharename,
9336                                            r->in.key_name,
9337                                            r->in.value_name,
9338                                            r->in.type,
9339                                            r->in.data,
9340                                            r->in.offered);
9341
9342         if (W_ERROR_IS_OK(result)) {
9343                 /* save the OID if one was specified */
9344                 if (oid_string) {
9345                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9346                                 r->in.key_name, SPOOL_OID_KEY);
9347                         if (!str) {
9348                                 result = WERR_NOMEM;
9349                                 goto done;
9350                         }
9351
9352                         /*
9353                          * I'm not checking the status here on purpose.  Don't know
9354                          * if this is right, but I'm returning the status from the
9355                          * previous set_printer_dataex() call.  I have no idea if
9356                          * this is right.    --jerry
9357                          */
9358                         winreg_set_printer_dataex(p->mem_ctx,
9359                                                   get_session_info_system(),
9360                                                   p->msg_ctx,
9361                                                   pinfo2->sharename,
9362                                                   str,
9363                                                   r->in.value_name,
9364                                                   REG_SZ,
9365                                                   (uint8_t *) oid_string,
9366                                                   strlen(oid_string) + 1);
9367                 }
9368
9369                 result = winreg_printer_update_changeid(p->mem_ctx,
9370                                                         get_session_info_system(),
9371                                                         p->msg_ctx,
9372                                                         lp_const_servicename(snum));
9373
9374         }
9375
9376 done:
9377         talloc_free(pinfo2);
9378         return result;
9379 }
9380
9381 /****************************************************************
9382  _spoolss_DeletePrinterDataEx
9383 ****************************************************************/
9384
9385 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9386                                     struct spoolss_DeletePrinterDataEx *r)
9387 {
9388         const char *printer;
9389         int             snum=0;
9390         WERROR          status = WERR_OK;
9391         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9392
9393         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9394
9395         if (!Printer) {
9396                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9397                         "Invalid handle (%s:%u:%u).\n",
9398                         OUR_HANDLE(r->in.handle)));
9399                 return WERR_BADFID;
9400         }
9401
9402         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9403                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9404                         "printer properties change denied by handle\n"));
9405                 return WERR_ACCESS_DENIED;
9406         }
9407
9408         if (!r->in.value_name || !r->in.key_name) {
9409                 return WERR_NOMEM;
9410         }
9411
9412         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9413                 return WERR_BADFID;
9414         }
9415         printer = lp_const_servicename(snum);
9416
9417         status = winreg_delete_printer_dataex(p->mem_ctx,
9418                                               get_session_info_system(),
9419                                               p->msg_ctx,
9420                                               printer,
9421                                               r->in.key_name,
9422                                               r->in.value_name);
9423         if (W_ERROR_IS_OK(status)) {
9424                 status = winreg_printer_update_changeid(p->mem_ctx,
9425                                                         get_session_info_system(),
9426                                                         p->msg_ctx,
9427                                                         printer);
9428         }
9429
9430         return status;
9431 }
9432
9433 /****************************************************************
9434  _spoolss_EnumPrinterKey
9435 ****************************************************************/
9436
9437 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9438                                struct spoolss_EnumPrinterKey *r)
9439 {
9440         uint32_t        num_keys;
9441         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9442         int             snum = 0;
9443         WERROR          result = WERR_BADFILE;
9444         const char **array = NULL;
9445         DATA_BLOB blob;
9446
9447         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9448
9449         if (!Printer) {
9450                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9451                         OUR_HANDLE(r->in.handle)));
9452                 return WERR_BADFID;
9453         }
9454
9455         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9456                 return WERR_BADFID;
9457         }
9458
9459         result = winreg_enum_printer_key(p->mem_ctx,
9460                                          get_session_info_system(),
9461                                          p->msg_ctx,
9462                                          lp_const_servicename(snum),
9463                                          r->in.key_name,
9464                                          &num_keys,
9465                                          &array);
9466         if (!W_ERROR_IS_OK(result)) {
9467                 goto done;
9468         }
9469
9470         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9471                 result = WERR_NOMEM;
9472                 goto done;
9473         }
9474
9475         *r->out._ndr_size = r->in.offered / 2;
9476         *r->out.needed = blob.length;
9477
9478         if (r->in.offered < *r->out.needed) {
9479                 result = WERR_MORE_DATA;
9480         } else {
9481                 result = WERR_OK;
9482                 r->out.key_buffer->string_array = array;
9483         }
9484
9485  done:
9486         if (!W_ERROR_IS_OK(result)) {
9487                 TALLOC_FREE(array);
9488                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9489                         *r->out.needed = 0;
9490                 }
9491         }
9492
9493         return result;
9494 }
9495
9496 /****************************************************************
9497  _spoolss_DeletePrinterKey
9498 ****************************************************************/
9499
9500 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9501                                  struct spoolss_DeletePrinterKey *r)
9502 {
9503         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9504         int                     snum=0;
9505         WERROR                  status;
9506         const char *printer;
9507
9508         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9509
9510         if (!Printer) {
9511                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9512                         OUR_HANDLE(r->in.handle)));
9513                 return WERR_BADFID;
9514         }
9515
9516         /* if keyname == NULL, return error */
9517         if ( !r->in.key_name )
9518                 return WERR_INVALID_PARAM;
9519
9520         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9521                 return WERR_BADFID;
9522         }
9523
9524         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9525                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9526                         "printer properties change denied by handle\n"));
9527                 return WERR_ACCESS_DENIED;
9528         }
9529
9530         printer = lp_const_servicename(snum);
9531
9532         /* delete the key and all subkeys */
9533         status = winreg_delete_printer_key(p->mem_ctx,
9534                                            get_session_info_system(),
9535                                            p->msg_ctx,
9536                                            printer,
9537                                            r->in.key_name);
9538         if (W_ERROR_IS_OK(status)) {
9539                 status = winreg_printer_update_changeid(p->mem_ctx,
9540                                                         get_session_info_system(),
9541                                                         p->msg_ctx,
9542                                                         printer);
9543         }
9544
9545         return status;
9546 }
9547
9548 /****************************************************************
9549  _spoolss_EnumPrinterDataEx
9550 ****************************************************************/
9551
9552 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9553                                   struct spoolss_EnumPrinterDataEx *r)
9554 {
9555         uint32_t        count = 0;
9556         struct spoolss_PrinterEnumValues *info = NULL;
9557         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9558         int             snum;
9559         WERROR          result;
9560
9561         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9562
9563         *r->out.count = 0;
9564         *r->out.needed = 0;
9565         *r->out.info = NULL;
9566
9567         if (!Printer) {
9568                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9569                         OUR_HANDLE(r->in.handle)));
9570                 return WERR_BADFID;
9571         }
9572
9573         /*
9574          * first check for a keyname of NULL or "".  Win2k seems to send
9575          * this a lot and we should send back WERR_INVALID_PARAM
9576          * no need to spend time looking up the printer in this case.
9577          * --jerry
9578          */
9579
9580         if (!strlen(r->in.key_name)) {
9581                 result = WERR_INVALID_PARAM;
9582                 goto done;
9583         }
9584
9585         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9586                 return WERR_BADFID;
9587         }
9588
9589         /* now look for a match on the key name */
9590         result = winreg_enum_printer_dataex(p->mem_ctx,
9591                                             get_session_info_system(),
9592                                             p->msg_ctx,
9593                                             lp_const_servicename(snum),
9594                                             r->in.key_name,
9595                                             &count,
9596                                             &info);
9597         if (!W_ERROR_IS_OK(result)) {
9598                 goto done;
9599         }
9600
9601 #if 0 /* FIXME - gd */
9602         /* housekeeping information in the reply */
9603
9604         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9605          * the hand marshalled container size is a multiple
9606          * of 4 bytes for RPC alignment.
9607          */
9608
9609         if (needed % 4) {
9610                 needed += 4-(needed % 4);
9611         }
9612 #endif
9613         *r->out.count   = count;
9614         *r->out.info    = info;
9615
9616  done:
9617         if (!W_ERROR_IS_OK(result)) {
9618                 return result;
9619         }
9620
9621         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9622                                                spoolss_EnumPrinterDataEx,
9623                                                *r->out.info,
9624                                                *r->out.count);
9625         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9626         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9627
9628         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9629 }
9630
9631 /****************************************************************************
9632 ****************************************************************************/
9633
9634 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9635                                                  const char *servername,
9636                                                  const char *environment,
9637                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9638 {
9639         WERROR werr;
9640         char *path = NULL;
9641
9642         werr = compose_spoolss_server_path(mem_ctx,
9643                                            servername,
9644                                            environment,
9645                                            SPOOLSS_PRTPROCS_PATH,
9646                                            &path);
9647         if (!W_ERROR_IS_OK(werr)) {
9648                 return werr;
9649         }
9650
9651         DEBUG(4,("print processor directory: [%s]\n", path));
9652
9653         r->directory_name = path;
9654
9655         return WERR_OK;
9656 }
9657
9658 /****************************************************************
9659  _spoolss_GetPrintProcessorDirectory
9660 ****************************************************************/
9661
9662 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9663                                            struct spoolss_GetPrintProcessorDirectory *r)
9664 {
9665         WERROR result;
9666         char *prnproc_share = NULL;
9667         bool prnproc_share_exists = false;
9668         int snum;
9669
9670         /* that's an [in out] buffer */
9671
9672         if (!r->in.buffer && (r->in.offered != 0)) {
9673                 return WERR_INVALID_PARAM;
9674         }
9675
9676         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9677                 r->in.level));
9678
9679         *r->out.needed = 0;
9680
9681         /* r->in.level is ignored */
9682
9683         /* We always should reply with a local print processor directory so that
9684          * users are not forced to have a [prnproc$] share on the Samba spoolss
9685          * server, if users decide to do so, lets announce it though - Guenther */
9686
9687         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9688         if (!prnproc_share) {
9689                 return WERR_NOMEM;
9690         }
9691         if (snum != -1) {
9692                 prnproc_share_exists = true;
9693         }
9694
9695         result = getprintprocessordirectory_level_1(p->mem_ctx,
9696                                                     prnproc_share_exists ? r->in.server : NULL,
9697                                                     r->in.environment,
9698                                                     &r->out.info->info1);
9699         if (!W_ERROR_IS_OK(result)) {
9700                 TALLOC_FREE(r->out.info);
9701                 return result;
9702         }
9703
9704         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9705                                                                                    r->out.info, r->in.level);
9706         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9707
9708         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9709 }
9710
9711 /*******************************************************************
9712  ********************************************************************/
9713
9714 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9715                                const char *dllname)
9716 {
9717         enum ndr_err_code ndr_err;
9718         struct spoolss_MonitorUi ui;
9719
9720         ui.dll_name = dllname;
9721
9722         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9723                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9724         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9725                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9726         }
9727         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9728 }
9729
9730 /*******************************************************************
9731  Streams the monitor UI DLL name in UNICODE
9732 *******************************************************************/
9733
9734 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9735                                struct security_token *token, DATA_BLOB *in,
9736                                DATA_BLOB *out, uint32_t *needed)
9737 {
9738         const char *dllname = "tcpmonui.dll";
9739
9740         *needed = (strlen(dllname)+1) * 2;
9741
9742         if (out->length < *needed) {
9743                 return WERR_INSUFFICIENT_BUFFER;
9744         }
9745
9746         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9747                 return WERR_NOMEM;
9748         }
9749
9750         return WERR_OK;
9751 }
9752
9753 /*******************************************************************
9754  ********************************************************************/
9755
9756 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9757                              struct spoolss_PortData1 *port1,
9758                              const DATA_BLOB *buf)
9759 {
9760         enum ndr_err_code ndr_err;
9761         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9762                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9763         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9764                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9765         }
9766         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9767 }
9768
9769 /*******************************************************************
9770  ********************************************************************/
9771
9772 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9773                              struct spoolss_PortData2 *port2,
9774                              const DATA_BLOB *buf)
9775 {
9776         enum ndr_err_code ndr_err;
9777         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9778                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9779         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9780                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9781         }
9782         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9783 }
9784
9785 /*******************************************************************
9786  Create a new TCP/IP port
9787 *******************************************************************/
9788
9789 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9790                              struct security_token *token, DATA_BLOB *in,
9791                              DATA_BLOB *out, uint32_t *needed)
9792 {
9793         struct spoolss_PortData1 port1;
9794         struct spoolss_PortData2 port2;
9795         char *device_uri = NULL;
9796         uint32_t version;
9797
9798         const char *portname;
9799         const char *hostaddress;
9800         const char *queue;
9801         uint32_t port_number;
9802         uint32_t protocol;
9803
9804         /* peek for spoolss_PortData version */
9805
9806         if (!in || (in->length < (128 + 4))) {
9807                 return WERR_GENERAL_FAILURE;
9808         }
9809
9810         version = IVAL(in->data, 128);
9811
9812         switch (version) {
9813                 case 1:
9814                         ZERO_STRUCT(port1);
9815
9816                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9817                                 return WERR_NOMEM;
9818                         }
9819
9820                         portname        = port1.portname;
9821                         hostaddress     = port1.hostaddress;
9822                         queue           = port1.queue;
9823                         protocol        = port1.protocol;
9824                         port_number     = port1.port_number;
9825
9826                         break;
9827                 case 2:
9828                         ZERO_STRUCT(port2);
9829
9830                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9831                                 return WERR_NOMEM;
9832                         }
9833
9834                         portname        = port2.portname;
9835                         hostaddress     = port2.hostaddress;
9836                         queue           = port2.queue;
9837                         protocol        = port2.protocol;
9838                         port_number     = port2.port_number;
9839
9840                         break;
9841                 default:
9842                         DEBUG(1,("xcvtcp_addport: "
9843                                 "unknown version of port_data: %d\n", version));
9844                         return WERR_UNKNOWN_PORT;
9845         }
9846
9847         /* create the device URI and call the add_port_hook() */
9848
9849         switch (protocol) {
9850         case PROTOCOL_RAWTCP_TYPE:
9851                 device_uri = talloc_asprintf(mem_ctx,
9852                                 "socket://%s:%d/", hostaddress,
9853                                 port_number);
9854                 break;
9855
9856         case PROTOCOL_LPR_TYPE:
9857                 device_uri = talloc_asprintf(mem_ctx,
9858                         "lpr://%s/%s", hostaddress, queue );
9859                 break;
9860
9861         default:
9862                 return WERR_UNKNOWN_PORT;
9863         }
9864
9865         if (!device_uri) {
9866                 return WERR_NOMEM;
9867         }
9868
9869         return add_port_hook(mem_ctx, token, portname, device_uri);
9870 }
9871
9872 /*******************************************************************
9873 *******************************************************************/
9874
9875 struct xcv_api_table xcvtcp_cmds[] = {
9876         { "MonitorUI",  xcvtcp_monitorui },
9877         { "AddPort",    xcvtcp_addport},
9878         { NULL,         NULL }
9879 };
9880
9881 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9882                                      struct security_token *token, const char *command,
9883                                      DATA_BLOB *inbuf,
9884                                      DATA_BLOB *outbuf,
9885                                      uint32_t *needed )
9886 {
9887         int i;
9888
9889         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9890
9891         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9892                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9893                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9894         }
9895
9896         return WERR_BADFUNC;
9897 }
9898
9899 /*******************************************************************
9900 *******************************************************************/
9901 #if 0   /* don't support management using the "Local Port" monitor */
9902
9903 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9904                                  struct security_token *token, DATA_BLOB *in,
9905                                  DATA_BLOB *out, uint32_t *needed)
9906 {
9907         const char *dllname = "localui.dll";
9908
9909         *needed = (strlen(dllname)+1) * 2;
9910
9911         if (out->length < *needed) {
9912                 return WERR_INSUFFICIENT_BUFFER;
9913         }
9914
9915         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9916                 return WERR_NOMEM;
9917         }
9918
9919         return WERR_OK;
9920 }
9921
9922 /*******************************************************************
9923 *******************************************************************/
9924
9925 struct xcv_api_table xcvlocal_cmds[] = {
9926         { "MonitorUI",  xcvlocal_monitorui },
9927         { NULL,         NULL }
9928 };
9929 #else
9930 struct xcv_api_table xcvlocal_cmds[] = {
9931         { NULL,         NULL }
9932 };
9933 #endif
9934
9935
9936
9937 /*******************************************************************
9938 *******************************************************************/
9939
9940 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9941                                        struct security_token *token, const char *command,
9942                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9943                                        uint32_t *needed)
9944 {
9945         int i;
9946
9947         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9948
9949         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9950                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9951                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9952         }
9953         return WERR_BADFUNC;
9954 }
9955
9956 /****************************************************************
9957  _spoolss_XcvData
9958 ****************************************************************/
9959
9960 WERROR _spoolss_XcvData(struct pipes_struct *p,
9961                         struct spoolss_XcvData *r)
9962 {
9963         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9964         DATA_BLOB out_data = data_blob_null;
9965         WERROR werror;
9966
9967         if (!Printer) {
9968                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9969                         OUR_HANDLE(r->in.handle)));
9970                 return WERR_BADFID;
9971         }
9972
9973         /* Has to be a handle to the TCP/IP port monitor */
9974
9975         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9976                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9977                 return WERR_BADFID;
9978         }
9979
9980         /* requires administrative access to the server */
9981
9982         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9983                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9984                 return WERR_ACCESS_DENIED;
9985         }
9986
9987         /* Allocate the outgoing buffer */
9988
9989         if (r->in.out_data_size) {
9990                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9991                 if (out_data.data == NULL) {
9992                         return WERR_NOMEM;
9993                 }
9994         }
9995
9996         switch ( Printer->printer_type ) {
9997         case SPLHND_PORTMON_TCP:
9998                 werror = process_xcvtcp_command(p->mem_ctx,
9999                                                 p->session_info->security_token,
10000                                                 r->in.function_name,
10001                                                 &r->in.in_data, &out_data,
10002                                                 r->out.needed);
10003                 break;
10004         case SPLHND_PORTMON_LOCAL:
10005                 werror = process_xcvlocal_command(p->mem_ctx,
10006                                                   p->session_info->security_token,
10007                                                   r->in.function_name,
10008                                                   &r->in.in_data, &out_data,
10009                                                   r->out.needed);
10010                 break;
10011         default:
10012                 werror = WERR_INVALID_PRINT_MONITOR;
10013         }
10014
10015         if (!W_ERROR_IS_OK(werror)) {
10016                 return werror;
10017         }
10018
10019         *r->out.status_code = 0;
10020
10021         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10022                 memcpy(r->out.out_data, out_data.data,
10023                         MIN(r->in.out_data_size, out_data.length));
10024         }
10025
10026         return WERR_OK;
10027 }
10028
10029 /****************************************************************
10030  _spoolss_AddPrintProcessor
10031 ****************************************************************/
10032
10033 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10034                                   struct spoolss_AddPrintProcessor *r)
10035 {
10036         /* for now, just indicate success and ignore the add.  We'll
10037            automatically set the winprint processor for printer
10038            entries later.  Used to debug the LexMark Optra S 1855 PCL
10039            driver --jerry */
10040
10041         return WERR_OK;
10042 }
10043
10044 /****************************************************************
10045  _spoolss_AddPort
10046 ****************************************************************/
10047
10048 WERROR _spoolss_AddPort(struct pipes_struct *p,
10049                         struct spoolss_AddPort *r)
10050 {
10051         /* do what w2k3 does */
10052
10053         return WERR_NOT_SUPPORTED;
10054 }
10055
10056 /****************************************************************
10057  _spoolss_GetPrinterDriver
10058 ****************************************************************/
10059
10060 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10061                                  struct spoolss_GetPrinterDriver *r)
10062 {
10063         p->rng_fault_state = true;
10064         return WERR_NOT_SUPPORTED;
10065 }
10066
10067 /****************************************************************
10068  _spoolss_ReadPrinter
10069 ****************************************************************/
10070
10071 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10072                             struct spoolss_ReadPrinter *r)
10073 {
10074         p->rng_fault_state = true;
10075         return WERR_NOT_SUPPORTED;
10076 }
10077
10078 /****************************************************************
10079  _spoolss_WaitForPrinterChange
10080 ****************************************************************/
10081
10082 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10083                                      struct spoolss_WaitForPrinterChange *r)
10084 {
10085         p->rng_fault_state = true;
10086         return WERR_NOT_SUPPORTED;
10087 }
10088
10089 /****************************************************************
10090  _spoolss_ConfigurePort
10091 ****************************************************************/
10092
10093 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10094                               struct spoolss_ConfigurePort *r)
10095 {
10096         p->rng_fault_state = true;
10097         return WERR_NOT_SUPPORTED;
10098 }
10099
10100 /****************************************************************
10101  _spoolss_DeletePort
10102 ****************************************************************/
10103
10104 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10105                            struct spoolss_DeletePort *r)
10106 {
10107         p->rng_fault_state = true;
10108         return WERR_NOT_SUPPORTED;
10109 }
10110
10111 /****************************************************************
10112  _spoolss_CreatePrinterIC
10113 ****************************************************************/
10114
10115 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10116                                 struct spoolss_CreatePrinterIC *r)
10117 {
10118         p->rng_fault_state = true;
10119         return WERR_NOT_SUPPORTED;
10120 }
10121
10122 /****************************************************************
10123  _spoolss_PlayGDIScriptOnPrinterIC
10124 ****************************************************************/
10125
10126 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10127                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10128 {
10129         p->rng_fault_state = true;
10130         return WERR_NOT_SUPPORTED;
10131 }
10132
10133 /****************************************************************
10134  _spoolss_DeletePrinterIC
10135 ****************************************************************/
10136
10137 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10138                                 struct spoolss_DeletePrinterIC *r)
10139 {
10140         p->rng_fault_state = true;
10141         return WERR_NOT_SUPPORTED;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_AddPrinterConnection
10146 ****************************************************************/
10147
10148 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10149                                      struct spoolss_AddPrinterConnection *r)
10150 {
10151         p->rng_fault_state = true;
10152         return WERR_NOT_SUPPORTED;
10153 }
10154
10155 /****************************************************************
10156  _spoolss_DeletePrinterConnection
10157 ****************************************************************/
10158
10159 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10160                                         struct spoolss_DeletePrinterConnection *r)
10161 {
10162         p->rng_fault_state = true;
10163         return WERR_NOT_SUPPORTED;
10164 }
10165
10166 /****************************************************************
10167  _spoolss_PrinterMessageBox
10168 ****************************************************************/
10169
10170 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10171                                   struct spoolss_PrinterMessageBox *r)
10172 {
10173         p->rng_fault_state = true;
10174         return WERR_NOT_SUPPORTED;
10175 }
10176
10177 /****************************************************************
10178  _spoolss_AddMonitor
10179 ****************************************************************/
10180
10181 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10182                            struct spoolss_AddMonitor *r)
10183 {
10184         p->rng_fault_state = true;
10185         return WERR_NOT_SUPPORTED;
10186 }
10187
10188 /****************************************************************
10189  _spoolss_DeleteMonitor
10190 ****************************************************************/
10191
10192 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10193                               struct spoolss_DeleteMonitor *r)
10194 {
10195         p->rng_fault_state = true;
10196         return WERR_NOT_SUPPORTED;
10197 }
10198
10199 /****************************************************************
10200  _spoolss_DeletePrintProcessor
10201 ****************************************************************/
10202
10203 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10204                                      struct spoolss_DeletePrintProcessor *r)
10205 {
10206         p->rng_fault_state = true;
10207         return WERR_NOT_SUPPORTED;
10208 }
10209
10210 /****************************************************************
10211  _spoolss_AddPrintProvidor
10212 ****************************************************************/
10213
10214 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10215                                  struct spoolss_AddPrintProvidor *r)
10216 {
10217         p->rng_fault_state = true;
10218         return WERR_NOT_SUPPORTED;
10219 }
10220
10221 /****************************************************************
10222  _spoolss_DeletePrintProvidor
10223 ****************************************************************/
10224
10225 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10226                                     struct spoolss_DeletePrintProvidor *r)
10227 {
10228         p->rng_fault_state = true;
10229         return WERR_NOT_SUPPORTED;
10230 }
10231
10232 /****************************************************************
10233  _spoolss_FindFirstPrinterChangeNotification
10234 ****************************************************************/
10235
10236 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10237                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10238 {
10239         p->rng_fault_state = true;
10240         return WERR_NOT_SUPPORTED;
10241 }
10242
10243 /****************************************************************
10244  _spoolss_FindNextPrinterChangeNotification
10245 ****************************************************************/
10246
10247 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10248                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10249 {
10250         p->rng_fault_state = true;
10251         return WERR_NOT_SUPPORTED;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10256 ****************************************************************/
10257
10258 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10259                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10260 {
10261         p->rng_fault_state = true;
10262         return WERR_NOT_SUPPORTED;
10263 }
10264
10265 /****************************************************************
10266  _spoolss_ReplyOpenPrinter
10267 ****************************************************************/
10268
10269 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10270                                  struct spoolss_ReplyOpenPrinter *r)
10271 {
10272         p->rng_fault_state = true;
10273         return WERR_NOT_SUPPORTED;
10274 }
10275
10276 /****************************************************************
10277  _spoolss_RouterReplyPrinter
10278 ****************************************************************/
10279
10280 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10281                                    struct spoolss_RouterReplyPrinter *r)
10282 {
10283         p->rng_fault_state = true;
10284         return WERR_NOT_SUPPORTED;
10285 }
10286
10287 /****************************************************************
10288  _spoolss_ReplyClosePrinter
10289 ****************************************************************/
10290
10291 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10292                                   struct spoolss_ReplyClosePrinter *r)
10293 {
10294         p->rng_fault_state = true;
10295         return WERR_NOT_SUPPORTED;
10296 }
10297
10298 /****************************************************************
10299  _spoolss_AddPortEx
10300 ****************************************************************/
10301
10302 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10303                           struct spoolss_AddPortEx *r)
10304 {
10305         p->rng_fault_state = true;
10306         return WERR_NOT_SUPPORTED;
10307 }
10308
10309 /****************************************************************
10310  _spoolss_RouterFindFirstPrinterChangeNotification
10311 ****************************************************************/
10312
10313 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10314                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10315 {
10316         p->rng_fault_state = true;
10317         return WERR_NOT_SUPPORTED;
10318 }
10319
10320 /****************************************************************
10321  _spoolss_SpoolerInit
10322 ****************************************************************/
10323
10324 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10325                             struct spoolss_SpoolerInit *r)
10326 {
10327         p->rng_fault_state = true;
10328         return WERR_NOT_SUPPORTED;
10329 }
10330
10331 /****************************************************************
10332  _spoolss_ResetPrinterEx
10333 ****************************************************************/
10334
10335 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10336                                struct spoolss_ResetPrinterEx *r)
10337 {
10338         p->rng_fault_state = true;
10339         return WERR_NOT_SUPPORTED;
10340 }
10341
10342 /****************************************************************
10343  _spoolss_RouterReplyPrinterEx
10344 ****************************************************************/
10345
10346 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10347                                      struct spoolss_RouterReplyPrinterEx *r)
10348 {
10349         p->rng_fault_state = true;
10350         return WERR_NOT_SUPPORTED;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_44
10355 ****************************************************************/
10356
10357 WERROR _spoolss_44(struct pipes_struct *p,
10358                    struct spoolss_44 *r)
10359 {
10360         p->rng_fault_state = true;
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_SetPort
10366 ****************************************************************/
10367
10368 WERROR _spoolss_SetPort(struct pipes_struct *p,
10369                         struct spoolss_SetPort *r)
10370 {
10371         p->rng_fault_state = true;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_4a
10377 ****************************************************************/
10378
10379 WERROR _spoolss_4a(struct pipes_struct *p,
10380                    struct spoolss_4a *r)
10381 {
10382         p->rng_fault_state = true;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_4b
10388 ****************************************************************/
10389
10390 WERROR _spoolss_4b(struct pipes_struct *p,
10391                    struct spoolss_4b *r)
10392 {
10393         p->rng_fault_state = true;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_4c
10399 ****************************************************************/
10400
10401 WERROR _spoolss_4c(struct pipes_struct *p,
10402                    struct spoolss_4c *r)
10403 {
10404         p->rng_fault_state = true;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_53
10410 ****************************************************************/
10411
10412 WERROR _spoolss_53(struct pipes_struct *p,
10413                    struct spoolss_53 *r)
10414 {
10415         p->rng_fault_state = true;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_AddPerMachineConnection
10421 ****************************************************************/
10422
10423 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10424                                         struct spoolss_AddPerMachineConnection *r)
10425 {
10426         p->rng_fault_state = true;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_DeletePerMachineConnection
10432 ****************************************************************/
10433
10434 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10435                                            struct spoolss_DeletePerMachineConnection *r)
10436 {
10437         p->rng_fault_state = true;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_EnumPerMachineConnections
10443 ****************************************************************/
10444
10445 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10446                                           struct spoolss_EnumPerMachineConnections *r)
10447 {
10448         p->rng_fault_state = true;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_5a
10454 ****************************************************************/
10455
10456 WERROR _spoolss_5a(struct pipes_struct *p,
10457                    struct spoolss_5a *r)
10458 {
10459         p->rng_fault_state = true;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_5b
10465 ****************************************************************/
10466
10467 WERROR _spoolss_5b(struct pipes_struct *p,
10468                    struct spoolss_5b *r)
10469 {
10470         p->rng_fault_state = true;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_5c
10476 ****************************************************************/
10477
10478 WERROR _spoolss_5c(struct pipes_struct *p,
10479                    struct spoolss_5c *r)
10480 {
10481         p->rng_fault_state = true;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_5d
10487 ****************************************************************/
10488
10489 WERROR _spoolss_5d(struct pipes_struct *p,
10490                    struct spoolss_5d *r)
10491 {
10492         p->rng_fault_state = true;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_5e
10498 ****************************************************************/
10499
10500 WERROR _spoolss_5e(struct pipes_struct *p,
10501                    struct spoolss_5e *r)
10502 {
10503         p->rng_fault_state = true;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_5f
10509 ****************************************************************/
10510
10511 WERROR _spoolss_5f(struct pipes_struct *p,
10512                    struct spoolss_5f *r)
10513 {
10514         p->rng_fault_state = true;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_60
10520 ****************************************************************/
10521
10522 WERROR _spoolss_60(struct pipes_struct *p,
10523                    struct spoolss_60 *r)
10524 {
10525         p->rng_fault_state = true;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_61
10531 ****************************************************************/
10532
10533 WERROR _spoolss_61(struct pipes_struct *p,
10534                    struct spoolss_61 *r)
10535 {
10536         p->rng_fault_state = true;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_62
10542 ****************************************************************/
10543
10544 WERROR _spoolss_62(struct pipes_struct *p,
10545                    struct spoolss_62 *r)
10546 {
10547         p->rng_fault_state = true;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_63
10553 ****************************************************************/
10554
10555 WERROR _spoolss_63(struct pipes_struct *p,
10556                    struct spoolss_63 *r)
10557 {
10558         p->rng_fault_state = true;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_64
10564 ****************************************************************/
10565
10566 WERROR _spoolss_64(struct pipes_struct *p,
10567                    struct spoolss_64 *r)
10568 {
10569         p->rng_fault_state = true;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_65
10575 ****************************************************************/
10576
10577 WERROR _spoolss_65(struct pipes_struct *p,
10578                    struct spoolss_65 *r)
10579 {
10580         p->rng_fault_state = true;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_GetCorePrinterDrivers
10586 ****************************************************************/
10587
10588 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10589                                       struct spoolss_GetCorePrinterDrivers *r)
10590 {
10591         p->rng_fault_state = true;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_67
10597 ****************************************************************/
10598
10599 WERROR _spoolss_67(struct pipes_struct *p,
10600                    struct spoolss_67 *r)
10601 {
10602         p->rng_fault_state = true;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_GetPrinterDriverPackagePath
10608 ****************************************************************/
10609
10610 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10611                                             struct spoolss_GetPrinterDriverPackagePath *r)
10612 {
10613         p->rng_fault_state = true;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_69
10619 ****************************************************************/
10620
10621 WERROR _spoolss_69(struct pipes_struct *p,
10622                    struct spoolss_69 *r)
10623 {
10624         p->rng_fault_state = true;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_6a
10630 ****************************************************************/
10631
10632 WERROR _spoolss_6a(struct pipes_struct *p,
10633                    struct spoolss_6a *r)
10634 {
10635         p->rng_fault_state = true;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _spoolss_6b
10641 ****************************************************************/
10642
10643 WERROR _spoolss_6b(struct pipes_struct *p,
10644                    struct spoolss_6b *r)
10645 {
10646         p->rng_fault_state = true;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_6c
10652 ****************************************************************/
10653
10654 WERROR _spoolss_6c(struct pipes_struct *p,
10655                    struct spoolss_6c *r)
10656 {
10657         p->rng_fault_state = true;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_6d
10663 ****************************************************************/
10664
10665 WERROR _spoolss_6d(struct pipes_struct *p,
10666                    struct spoolss_6d *r)
10667 {
10668         p->rng_fault_state = true;
10669         return WERR_NOT_SUPPORTED;
10670 }