Fix some types
[kai/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
48 /* macros stolen from s4 spoolss server */
49 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
50         ((info)?ndr_size_##fn(info, level, 0):0)
51
52 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
53         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
54
55 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
56         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
57
58 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
59
60 #undef DBGC_CLASS
61 #define DBGC_CLASS DBGC_RPC_SRV
62
63 #ifndef MAX_OPEN_PRINTER_EXS
64 #define MAX_OPEN_PRINTER_EXS 50
65 #endif
66
67 struct notify_back_channel;
68
69 /* structure to store the printer handles */
70 /* and a reference to what it's pointing to */
71 /* and the notify info asked about */
72 /* that's the central struct */
73 struct printer_handle {
74         struct printer_handle *prev, *next;
75         bool document_started;
76         bool page_started;
77         uint32 jobid; /* jobid in printing backend */
78         int printer_type;
79         const char *servername;
80         fstring sharename;
81         uint32 type;
82         uint32 access_granted;
83         struct {
84                 uint32 flags;
85                 uint32 options;
86                 fstring localmachine;
87                 uint32 printerlocal;
88                 struct spoolss_NotifyOption *option;
89                 struct policy_handle cli_hnd;
90                 struct notify_back_channel *cli_chan;
91                 uint32 change;
92                 /* are we in a FindNextPrinterChangeNotify() call? */
93                 bool fnpcn;
94                 struct messaging_context *msg_ctx;
95         } notify;
96         struct {
97                 fstring machine;
98                 fstring user;
99         } client;
100
101         /* devmode sent in the OpenPrinter() call */
102         struct spoolss_DeviceMode *devmode;
103
104         /* TODO cache the printer info2 structure */
105         struct spoolss_PrinterInfo2 *info2;
106
107 };
108
109 static struct printer_handle *printers_list;
110
111 struct printer_session_counter {
112         struct printer_session_counter *next;
113         struct printer_session_counter *prev;
114
115         int snum;
116         uint32_t counter;
117 };
118
119 static struct printer_session_counter *counter_list;
120
121 struct notify_back_channel {
122         struct notify_back_channel *prev, *next;
123
124         /* associated client */
125         struct sockaddr_storage client_address;
126
127         /* print notify back-channel pipe handle*/
128         struct rpc_pipe_client *cli_pipe;
129         struct dcerpc_binding_handle *binding_handle;
130         uint32_t active_connections;
131 };
132
133 static struct notify_back_channel *back_channels;
134
135 /* Map generic permissions to printer object specific permissions */
136
137 const struct standard_mapping printer_std_mapping = {
138         PRINTER_READ,
139         PRINTER_WRITE,
140         PRINTER_EXECUTE,
141         PRINTER_ALL_ACCESS
142 };
143
144 /* Map generic permissions to print server object specific permissions */
145
146 const struct standard_mapping printserver_std_mapping = {
147         SERVER_READ,
148         SERVER_WRITE,
149         SERVER_EXECUTE,
150         SERVER_ALL_ACCESS
151 };
152
153 /* API table for Xcv Monitor functions */
154
155 struct xcv_api_table {
156         const char *name;
157         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
158 };
159
160 static void prune_printername_cache(void);
161
162 /********************************************************************
163  * Canonicalize servername.
164  ********************************************************************/
165
166 static const char *canon_servername(const char *servername)
167 {
168         const char *pservername = servername;
169         while (*pservername == '\\') {
170                 pservername++;
171         }
172         return pservername;
173 }
174
175 /* translate between internal status numbers and NT status numbers */
176 static int nt_printj_status(int v)
177 {
178         switch (v) {
179         case LPQ_QUEUED:
180                 return 0;
181         case LPQ_PAUSED:
182                 return JOB_STATUS_PAUSED;
183         case LPQ_SPOOLING:
184                 return JOB_STATUS_SPOOLING;
185         case LPQ_PRINTING:
186                 return JOB_STATUS_PRINTING;
187         case LPQ_ERROR:
188                 return JOB_STATUS_ERROR;
189         case LPQ_DELETING:
190                 return JOB_STATUS_DELETING;
191         case LPQ_OFFLINE:
192                 return JOB_STATUS_OFFLINE;
193         case LPQ_PAPEROUT:
194                 return JOB_STATUS_PAPEROUT;
195         case LPQ_PRINTED:
196                 return JOB_STATUS_PRINTED;
197         case LPQ_DELETED:
198                 return JOB_STATUS_DELETED;
199         case LPQ_BLOCKED:
200                 return JOB_STATUS_BLOCKED_DEVQ;
201         case LPQ_USER_INTERVENTION:
202                 return JOB_STATUS_USER_INTERVENTION;
203         }
204         return 0;
205 }
206
207 static int nt_printq_status(int v)
208 {
209         switch (v) {
210         case LPQ_PAUSED:
211                 return PRINTER_STATUS_PAUSED;
212         case LPQ_QUEUED:
213         case LPQ_SPOOLING:
214         case LPQ_PRINTING:
215                 return 0;
216         }
217         return 0;
218 }
219
220 /***************************************************************************
221  Disconnect from the client
222 ****************************************************************************/
223
224 static void srv_spoolss_replycloseprinter(int snum,
225                                           struct printer_handle *prn_hnd)
226 {
227         WERROR result;
228         NTSTATUS status;
229
230         /*
231          * Tell the specific printing tdb we no longer want messages for this printer
232          * by deregistering our PID.
233          */
234
235         if (!print_notify_deregister_pid(snum)) {
236                 DEBUG(0, ("Failed to register our pid for printer %s\n",
237                           lp_const_servicename(snum)));
238         }
239
240         /* weird if the test succeeds !!! */
241         if (prn_hnd->notify.cli_chan == NULL ||
242             prn_hnd->notify.cli_chan->active_connections == 0) {
243                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
244                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
245                 TALLOC_FREE(prn_hnd->notify.cli_chan);
246                 return;
247         }
248
249         status = dcerpc_spoolss_ReplyClosePrinter(
250                                         prn_hnd->notify.cli_chan->binding_handle,
251                                         talloc_tos(),
252                                         &prn_hnd->notify.cli_hnd,
253                                         &result);
254         if (!NT_STATUS_IS_OK(status)) {
255                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
256                           nt_errstr(status)));
257                 result = ntstatus_to_werror(status);
258         } else if (!W_ERROR_IS_OK(result)) {
259                 DEBUG(0, ("reply_close_printer failed [%s].\n",
260                           win_errstr(result)));
261         }
262
263         /* if it's the last connection, deconnect the IPC$ share */
264         if (prn_hnd->notify.cli_chan->active_connections == 1) {
265
266                 prn_hnd->notify.cli_chan->binding_handle = NULL;
267                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
268                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
269                 TALLOC_FREE(prn_hnd->notify.cli_chan);
270
271                 if (prn_hnd->notify.msg_ctx != NULL) {
272                         messaging_deregister(prn_hnd->notify.msg_ctx,
273                                              MSG_PRINTER_NOTIFY2, NULL);
274
275                         /*
276                          * Tell the serverid.tdb we're no longer
277                          * interested in printer notify messages.
278                          */
279
280                         serverid_register_msg_flags(
281                                 messaging_server_id(prn_hnd->notify.msg_ctx),
282                                 false, FLAG_MSG_PRINT_NOTIFY);
283                 }
284         }
285
286         if (prn_hnd->notify.cli_chan) {
287                 prn_hnd->notify.cli_chan->active_connections--;
288         }
289 }
290
291 /****************************************************************************
292  Functions to free a printer entry datastruct.
293 ****************************************************************************/
294
295 static int printer_entry_destructor(struct printer_handle *Printer)
296 {
297         if (Printer->notify.cli_chan != NULL &&
298             Printer->notify.cli_chan->active_connections > 0) {
299                 int snum = -1;
300
301                 switch(Printer->printer_type) {
302                 case SPLHND_SERVER:
303                         srv_spoolss_replycloseprinter(snum, Printer);
304                         break;
305
306                 case SPLHND_PRINTER:
307                         snum = print_queue_snum(Printer->sharename);
308                         if (snum != -1) {
309                                 srv_spoolss_replycloseprinter(snum, Printer);
310                         }
311                         break;
312                 default:
313                         break;
314                 }
315         }
316
317         Printer->notify.flags=0;
318         Printer->notify.options=0;
319         Printer->notify.localmachine[0]='\0';
320         Printer->notify.printerlocal=0;
321         TALLOC_FREE(Printer->notify.option);
322         TALLOC_FREE(Printer->devmode);
323
324         /* Remove from the internal list. */
325         DLIST_REMOVE(printers_list, Printer);
326         return 0;
327 }
328
329 /****************************************************************************
330   find printer index by handle
331 ****************************************************************************/
332
333 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
334                                                         struct policy_handle *hnd)
335 {
336         struct printer_handle *find_printer = NULL;
337
338         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
339                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
340                 return NULL;
341         }
342
343         return find_printer;
344 }
345
346 /****************************************************************************
347  Close printer index by handle.
348 ****************************************************************************/
349
350 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
351 {
352         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
353
354         if (!Printer) {
355                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
356                         OUR_HANDLE(hnd)));
357                 return false;
358         }
359
360         close_policy_hnd(p, hnd);
361
362         return true;
363 }
364
365 /****************************************************************************
366  Delete a printer given a handle.
367 ****************************************************************************/
368
369 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
370                                   const char *sharename,
371                                   struct messaging_context *msg_ctx)
372 {
373         char *cmd = lp_deleteprinter_cmd();
374         char *command = NULL;
375         int ret;
376         bool is_print_op = false;
377
378         /* can't fail if we don't try */
379
380         if ( !*cmd )
381                 return WERR_OK;
382
383         command = talloc_asprintf(ctx,
384                         "%s \"%s\"",
385                         cmd, sharename);
386         if (!command) {
387                 return WERR_NOMEM;
388         }
389         if ( token )
390                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
391
392         DEBUG(10,("Running [%s]\n", command));
393
394         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
395
396         if ( is_print_op )
397                 become_root();
398
399         if ( (ret = smbrun(command, NULL)) == 0 ) {
400                 /* Tell everyone we updated smb.conf. */
401                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
402         }
403
404         if ( is_print_op )
405                 unbecome_root();
406
407         /********** END SePrintOperatorPrivlege BLOCK **********/
408
409         DEBUGADD(10,("returned [%d]\n", ret));
410
411         TALLOC_FREE(command);
412
413         if (ret != 0)
414                 return WERR_BADFID; /* What to return here? */
415
416         /* go ahead and re-read the services immediately */
417         become_root();
418         reload_services(msg_ctx, -1, false);
419         unbecome_root();
420
421         if ( lp_servicenumber( sharename ) >= 0 )
422                 return WERR_ACCESS_DENIED;
423
424         return WERR_OK;
425 }
426
427 /****************************************************************************
428  Delete a printer given a handle.
429 ****************************************************************************/
430
431 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
432 {
433         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
434         WERROR result;
435
436         if (!Printer) {
437                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
438                         OUR_HANDLE(hnd)));
439                 return WERR_BADFID;
440         }
441
442         /*
443          * It turns out that Windows allows delete printer on a handle
444          * opened by an admin user, then used on a pipe handle created
445          * by an anonymous user..... but they're working on security.... riiight !
446          * JRA.
447          */
448
449         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
450                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
451                 return WERR_ACCESS_DENIED;
452         }
453
454         /* this does not need a become root since the access check has been
455            done on the handle already */
456
457         result = winreg_delete_printer_key(p->mem_ctx,
458                                            get_session_info_system(),
459                                            p->msg_ctx,
460                                            Printer->sharename,
461                                            "");
462         if (!W_ERROR_IS_OK(result)) {
463                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
464                 return WERR_BADFID;
465         }
466
467         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
468                                      Printer->sharename, p->msg_ctx);
469         if (!W_ERROR_IS_OK(result)) {
470                 return result;
471         }
472         prune_printername_cache();
473         return WERR_OK;
474 }
475
476 /****************************************************************************
477  Return the snum of a printer corresponding to an handle.
478 ****************************************************************************/
479
480 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
481                              int *number, struct share_params **params)
482 {
483         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
484
485         if (!Printer) {
486                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
487                         OUR_HANDLE(hnd)));
488                 return false;
489         }
490
491         switch (Printer->printer_type) {
492                 case SPLHND_PRINTER:
493                         DEBUG(4,("short name:%s\n", Printer->sharename));
494                         *number = print_queue_snum(Printer->sharename);
495                         return (*number != -1);
496                 case SPLHND_SERVER:
497                         return false;
498                 default:
499                         return false;
500         }
501 }
502
503 /****************************************************************************
504  Set printer handle type.
505  Check if it's \\server or \\server\printer
506 ****************************************************************************/
507
508 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
509 {
510         DEBUG(3,("Setting printer type=%s\n", handlename));
511
512         /* it's a print server */
513         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
514                 DEBUGADD(4,("Printer is a print server\n"));
515                 Printer->printer_type = SPLHND_SERVER;
516         }
517         /* it's a printer (set_printer_hnd_name() will handle port monitors */
518         else {
519                 DEBUGADD(4,("Printer is a printer\n"));
520                 Printer->printer_type = SPLHND_PRINTER;
521         }
522
523         return true;
524 }
525
526 static void prune_printername_cache_fn(const char *key, const char *value,
527                                        time_t timeout, void *private_data)
528 {
529         gencache_del(key);
530 }
531
532 static void prune_printername_cache(void)
533 {
534         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
535 }
536
537 /****************************************************************************
538  Set printer handle name..  Accept names like \\server, \\server\printer,
539  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
540  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
541  XcvDataPort() interface.
542 ****************************************************************************/
543
544 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
545                                    const struct auth_serversupplied_info *session_info,
546                                    struct messaging_context *msg_ctx,
547                                    struct printer_handle *Printer,
548                                    const char *handlename)
549 {
550         int snum;
551         int n_services=lp_numservices();
552         char *aprinter;
553         const char *printername;
554         const char *servername = NULL;
555         fstring sname;
556         bool found = false;
557         struct spoolss_PrinterInfo2 *info2 = NULL;
558         WERROR result;
559         char *p;
560
561         /*
562          * Hopefully nobody names his printers like this. Maybe \ or ,
563          * are illegal in printer names even?
564          */
565         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
566         char *cache_key;
567         char *tmp;
568
569         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
570                 (unsigned long)strlen(handlename)));
571
572         aprinter = CONST_DISCARD(char *, handlename);
573         if ( *handlename == '\\' ) {
574                 servername = canon_servername(handlename);
575                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
576                         *aprinter = '\0';
577                         aprinter++;
578                 }
579                 if (!is_myname_or_ipaddr(servername)) {
580                         return WERR_INVALID_PRINTER_NAME;
581                 }
582                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
583                 if (Printer->servername == NULL) {
584                         return WERR_NOMEM;
585                 }
586         }
587
588         if (Printer->printer_type == SPLHND_SERVER) {
589                 return WERR_OK;
590         }
591
592         if (Printer->printer_type != SPLHND_PRINTER) {
593                 return WERR_INVALID_HANDLE;
594         }
595
596         DEBUGADD(5, ("searching for [%s]\n", aprinter));
597
598         p = strchr(aprinter, ',');
599         if (p != NULL) {
600                 char *p2 = p;
601                 p++;
602                 if (*p == ' ') {
603                         p++;
604                 }
605                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
606                         *p2 = '\0';
607                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
608                         *p2 = '\0';
609                 }
610         }
611
612         if (p) {
613                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
614         }
615
616         /* check for the Port Monitor Interface */
617         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
618                 Printer->printer_type = SPLHND_PORTMON_TCP;
619                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
620                 found = true;
621         }
622         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
623                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
624                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
625                 found = true;
626         }
627
628         /*
629          * With hundreds of printers, the "for" loop iterating all
630          * shares can be quite expensive, as it is done on every
631          * OpenPrinter. The loop maps "aprinter" to "sname", the
632          * result of which we cache in gencache.
633          */
634
635         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
636                                     aprinter);
637         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
638
639                 found = (strcmp(tmp, printer_not_found) != 0);
640                 if (!found) {
641                         DEBUG(4, ("Printer %s not found\n", aprinter));
642                         SAFE_FREE(tmp);
643                         return WERR_INVALID_PRINTER_NAME;
644                 }
645                 fstrcpy(sname, tmp);
646                 SAFE_FREE(tmp);
647         }
648
649         /* Search all sharenames first as this is easier than pulling
650            the printer_info_2 off of disk. Don't use find_service() since
651            that calls out to map_username() */
652
653         /* do another loop to look for printernames */
654         for (snum = 0; !found && snum < n_services; snum++) {
655                 const char *printer = lp_const_servicename(snum);
656
657                 /* no point going on if this is not a printer */
658                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
659                         continue;
660                 }
661
662                 /* ignore [printers] share */
663                 if (strequal(printer, "printers")) {
664                         continue;
665                 }
666
667                 fstrcpy(sname, printer);
668                 if (strequal(aprinter, printer)) {
669                         found = true;
670                         break;
671                 }
672
673                 /* no point looking up the printer object if
674                    we aren't allowing printername != sharename */
675                 if (lp_force_printername(snum)) {
676                         continue;
677                 }
678
679                 result = winreg_get_printer(mem_ctx,
680                                             session_info,
681                                             msg_ctx,
682                                             sname,
683                                             &info2);
684                 if ( !W_ERROR_IS_OK(result) ) {
685                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
686                                  sname, win_errstr(result)));
687                         continue;
688                 }
689
690                 printername = strrchr(info2->printername, '\\');
691                 if (printername == NULL) {
692                         printername = info2->printername;
693                 } else {
694                         printername++;
695                 }
696
697                 if (strequal(printername, aprinter)) {
698                         found = true;
699                         break;
700                 }
701
702                 DEBUGADD(10, ("printername: %s\n", printername));
703
704                 TALLOC_FREE(info2);
705         }
706
707         if ( !found ) {
708                 if (cache_key != NULL) {
709                         gencache_set(cache_key, printer_not_found,
710                                      time(NULL)+300);
711                         TALLOC_FREE(cache_key);
712                 }
713                 DEBUGADD(4,("Printer not found\n"));
714                 return WERR_INVALID_PRINTER_NAME;
715         }
716
717         if (cache_key != NULL) {
718                 gencache_set(cache_key, sname, time(NULL)+300);
719                 TALLOC_FREE(cache_key);
720         }
721
722         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
723
724         fstrcpy(Printer->sharename, sname);
725
726         return WERR_OK;
727 }
728
729 /****************************************************************************
730  Find first available printer slot. creates a printer handle for you.
731  ****************************************************************************/
732
733 static WERROR open_printer_hnd(struct pipes_struct *p,
734                                struct policy_handle *hnd,
735                                const char *name,
736                                uint32_t access_granted)
737 {
738         struct printer_handle *new_printer;
739         WERROR result;
740
741         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
742
743         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
744         if (new_printer == NULL) {
745                 return WERR_NOMEM;
746         }
747         talloc_set_destructor(new_printer, printer_entry_destructor);
748
749         /* This also steals the printer_handle on the policy_handle */
750         if (!create_policy_hnd(p, hnd, new_printer)) {
751                 TALLOC_FREE(new_printer);
752                 return WERR_INVALID_HANDLE;
753         }
754
755         /* Add to the internal list. */
756         DLIST_ADD(printers_list, new_printer);
757
758         new_printer->notify.option=NULL;
759
760         if (!set_printer_hnd_printertype(new_printer, name)) {
761                 close_printer_handle(p, hnd);
762                 return WERR_INVALID_HANDLE;
763         }
764
765         result = set_printer_hnd_name(p->mem_ctx,
766                                       get_session_info_system(),
767                                       p->msg_ctx,
768                                       new_printer, name);
769         if (!W_ERROR_IS_OK(result)) {
770                 close_printer_handle(p, hnd);
771                 return result;
772         }
773
774         new_printer->access_granted = access_granted;
775
776         DEBUG(5, ("%d printer handles active\n",
777                   (int)num_pipe_handles(p)));
778
779         return WERR_OK;
780 }
781
782 /***************************************************************************
783  check to see if the client motify handle is monitoring the notification
784  given by (notify_type, notify_field).
785  **************************************************************************/
786
787 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
788                                       uint16_t notify_field)
789 {
790         return true;
791 }
792
793 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
794                                 uint16_t notify_field)
795 {
796         struct spoolss_NotifyOption *option = p->notify.option;
797         uint32_t i, j;
798
799         /*
800          * Flags should always be zero when the change notify
801          * is registered by the client's spooler.  A user Win32 app
802          * might use the flags though instead of the NOTIFY_OPTION_INFO
803          * --jerry
804          */
805
806         if (!option) {
807                 return false;
808         }
809
810         if (p->notify.flags)
811                 return is_monitoring_event_flags(
812                         p->notify.flags, notify_type, notify_field);
813
814         for (i = 0; i < option->count; i++) {
815
816                 /* Check match for notify_type */
817
818                 if (option->types[i].type != notify_type)
819                         continue;
820
821                 /* Check match for field */
822
823                 for (j = 0; j < option->types[i].count; j++) {
824                         if (option->types[i].fields[j].field == notify_field) {
825                                 return true;
826                         }
827                 }
828         }
829
830         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
831                    p->servername, p->sharename, notify_type, notify_field));
832
833         return false;
834 }
835
836 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
837         _data->data.integer[0] = _integer; \
838         _data->data.integer[1] = 0;
839
840
841 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
842         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
843         if (!_data->data.string.string) {\
844                 _data->data.string.size = 0; \
845         } \
846         _data->data.string.size = strlen_m_term(_p) * 2;
847
848 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
849         _data->data.devmode.devmode = _devmode;
850
851 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
852         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
853         if (!_data->data.sd.sd) { \
854                 _data->data.sd.sd_size = 0; \
855         } \
856         _data->data.sd.sd_size = \
857                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
858
859 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
860                                    struct tm *t,
861                                    const char **pp,
862                                    uint32_t *plen)
863 {
864         struct spoolss_Time st;
865         uint32_t len = 16;
866         char *p;
867
868         if (!init_systemtime(&st, t)) {
869                 return;
870         }
871
872         p = talloc_array(mem_ctx, char, len);
873         if (!p) {
874                 return;
875         }
876
877         /*
878          * Systemtime must be linearized as a set of UINT16's.
879          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
880          */
881
882         SSVAL(p, 0, st.year);
883         SSVAL(p, 2, st.month);
884         SSVAL(p, 4, st.day_of_week);
885         SSVAL(p, 6, st.day);
886         SSVAL(p, 8, st.hour);
887         SSVAL(p, 10, st.minute);
888         SSVAL(p, 12, st.second);
889         SSVAL(p, 14, st.millisecond);
890
891         *pp = p;
892         *plen = len;
893 }
894
895 /* Convert a notification message to a struct spoolss_Notify */
896
897 static void notify_one_value(struct spoolss_notify_msg *msg,
898                              struct spoolss_Notify *data,
899                              TALLOC_CTX *mem_ctx)
900 {
901         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
902 }
903
904 static void notify_string(struct spoolss_notify_msg *msg,
905                           struct spoolss_Notify *data,
906                           TALLOC_CTX *mem_ctx)
907 {
908         /* The length of the message includes the trailing \0 */
909
910         data->data.string.size = msg->len * 2;
911         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
912         if (!data->data.string.string) {
913                 data->data.string.size = 0;
914                 return;
915         }
916 }
917
918 static void notify_system_time(struct spoolss_notify_msg *msg,
919                                struct spoolss_Notify *data,
920                                TALLOC_CTX *mem_ctx)
921 {
922         data->data.string.string = NULL;
923         data->data.string.size = 0;
924
925         if (msg->len != sizeof(time_t)) {
926                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
927                           msg->len));
928                 return;
929         }
930
931         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
932                                &data->data.string.string,
933                                &data->data.string.size);
934 }
935
936 struct notify2_message_table {
937         const char *name;
938         void (*fn)(struct spoolss_notify_msg *msg,
939                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
940 };
941
942 static struct notify2_message_table printer_notify_table[] = {
943         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
944         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
945         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
946         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
947         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
948         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
949         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
950         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
951         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
952         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
953         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
954         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
955         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
956         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
957         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
958         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
959         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
960         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
961         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
962 };
963
964 static struct notify2_message_table job_notify_table[] = {
965         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
966         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
967         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
968         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
969         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
970         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
971         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
972         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
973         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
974         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
975         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
976         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
977         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
978         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
979         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
980         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
981         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
982         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
983         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
984         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
985         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
986         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
987         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
988         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
989 };
990
991
992 /***********************************************************************
993  Allocate talloc context for container object
994  **********************************************************************/
995
996 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
997 {
998         if ( !ctr )
999                 return;
1000
1001         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1002
1003         return;
1004 }
1005
1006 /***********************************************************************
1007  release all allocated memory and zero out structure
1008  **********************************************************************/
1009
1010 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1011 {
1012         if ( !ctr )
1013                 return;
1014
1015         if ( ctr->ctx )
1016                 talloc_destroy(ctr->ctx);
1017
1018         ZERO_STRUCTP(ctr);
1019
1020         return;
1021 }
1022
1023 /***********************************************************************
1024  **********************************************************************/
1025
1026 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1027 {
1028         if ( !ctr )
1029                 return NULL;
1030
1031         return ctr->ctx;
1032 }
1033
1034 /***********************************************************************
1035  **********************************************************************/
1036
1037 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1038 {
1039         if ( !ctr || !ctr->msg_groups )
1040                 return NULL;
1041
1042         if ( idx >= ctr->num_groups )
1043                 return NULL;
1044
1045         return &ctr->msg_groups[idx];
1046
1047 }
1048
1049 /***********************************************************************
1050  How many groups of change messages do we have ?
1051  **********************************************************************/
1052
1053 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1054 {
1055         if ( !ctr )
1056                 return 0;
1057
1058         return ctr->num_groups;
1059 }
1060
1061 /***********************************************************************
1062  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1063  **********************************************************************/
1064
1065 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1066 {
1067         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1068         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1069         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1070         int                             i, new_slot;
1071
1072         if ( !ctr || !msg )
1073                 return 0;
1074
1075         /* loop over all groups looking for a matching printer name */
1076
1077         for ( i=0; i<ctr->num_groups; i++ ) {
1078                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1079                         break;
1080         }
1081
1082         /* add a new group? */
1083
1084         if ( i == ctr->num_groups ) {
1085                 ctr->num_groups++;
1086
1087                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1088                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1089                         return 0;
1090                 }
1091                 ctr->msg_groups = groups;
1092
1093                 /* clear the new entry and set the printer name */
1094
1095                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1096                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1097         }
1098
1099         /* add the change messages; 'i' is the correct index now regardless */
1100
1101         msg_grp = &ctr->msg_groups[i];
1102
1103         msg_grp->num_msgs++;
1104
1105         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1106                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1107                 return 0;
1108         }
1109         msg_grp->msgs = msg_list;
1110
1111         new_slot = msg_grp->num_msgs-1;
1112         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1113
1114         /* need to allocate own copy of data */
1115
1116         if ( msg->len != 0 )
1117                 msg_grp->msgs[new_slot].notify.data = (char *)
1118                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1119
1120         return ctr->num_groups;
1121 }
1122
1123 static void construct_info_data(struct spoolss_Notify *info_data,
1124                                 enum spoolss_NotifyType type,
1125                                 uint16_t field, int id);
1126
1127 /***********************************************************************
1128  Send a change notication message on all handles which have a call
1129  back registered
1130  **********************************************************************/
1131
1132 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1133                                   struct printer_handle *prn_hnd,
1134                                   SPOOLSS_NOTIFY_MSG *messages,
1135                                   uint32_t num_msgs,
1136                                   struct spoolss_Notify **_notifies,
1137                                   int *_count)
1138 {
1139         struct spoolss_Notify *notifies;
1140         SPOOLSS_NOTIFY_MSG *msg;
1141         int count = 0;
1142         uint32_t id;
1143         int i;
1144
1145         notifies = talloc_zero_array(mem_ctx,
1146                                      struct spoolss_Notify, num_msgs);
1147         if (!notifies) {
1148                 return ENOMEM;
1149         }
1150
1151         for (i = 0; i < num_msgs; i++) {
1152
1153                 msg = &messages[i];
1154
1155                 /* Are we monitoring this event? */
1156
1157                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1158                         continue;
1159                 }
1160
1161                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1162                            "for printer [%s]\n",
1163                            msg->type, msg->field, prn_hnd->sharename));
1164
1165                 /*
1166                  * if the is a printer notification handle and not a job
1167                  * notification type, then set the id to 0.
1168                  * Otherwise just use what was specified in the message.
1169                  *
1170                  * When registering change notification on a print server
1171                  * handle we always need to send back the id (snum) matching
1172                  * the printer for which the change took place.
1173                  * For change notify registered on a printer handle,
1174                  * this does not matter and the id should be 0.
1175                  *
1176                  * --jerry
1177                  */
1178
1179                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1180                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1181                         id = 0;
1182                 } else {
1183                         id = msg->id;
1184                 }
1185
1186                 /* Convert unix jobid to smb jobid */
1187
1188                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1189                         id = sysjob_to_jobid(msg->id);
1190
1191                         if (id == -1) {
1192                                 DEBUG(3, ("no such unix jobid %d\n",
1193                                           msg->id));
1194                                 continue;
1195                         }
1196                 }
1197
1198                 construct_info_data(&notifies[count],
1199                                     msg->type, msg->field, id);
1200
1201                 switch(msg->type) {
1202                 case PRINTER_NOTIFY_TYPE:
1203                         if (printer_notify_table[msg->field].fn) {
1204                                 printer_notify_table[msg->field].fn(msg,
1205                                                 &notifies[count], mem_ctx);
1206                         }
1207                         break;
1208
1209                 case JOB_NOTIFY_TYPE:
1210                         if (job_notify_table[msg->field].fn) {
1211                                 job_notify_table[msg->field].fn(msg,
1212                                                 &notifies[count], mem_ctx);
1213                         }
1214                         break;
1215
1216                 default:
1217                         DEBUG(5, ("Unknown notification type %d\n",
1218                                   msg->type));
1219                         continue;
1220                 }
1221
1222                 count++;
1223         }
1224
1225         *_notifies = notifies;
1226         *_count = count;
1227
1228         return 0;
1229 }
1230
1231 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1232                                 struct printer_handle *prn_hnd,
1233                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1234 {
1235         struct spoolss_Notify *notifies;
1236         int count = 0;
1237         union spoolss_ReplyPrinterInfo info;
1238         struct spoolss_NotifyInfo info0;
1239         uint32_t reply_result;
1240         NTSTATUS status;
1241         WERROR werr;
1242         int ret;
1243
1244         /* Is there notification on this handle? */
1245         if (prn_hnd->notify.cli_chan == NULL ||
1246             prn_hnd->notify.cli_chan->active_connections == 0) {
1247                 return 0;
1248         }
1249
1250         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1251                    prn_hnd->servername, prn_hnd->sharename));
1252
1253         /* For this printer? Print servers always receive notifications. */
1254         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1255             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1256                 return 0;
1257         }
1258
1259         DEBUG(10,("Our printer\n"));
1260
1261         /* build the array of change notifications */
1262         ret = build_notify2_messages(mem_ctx, prn_hnd,
1263                                      msg_group->msgs,
1264                                      msg_group->num_msgs,
1265                                      &notifies, &count);
1266         if (ret) {
1267                 return ret;
1268         }
1269
1270         info0.version   = 0x2;
1271         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1272         info0.count     = count;
1273         info0.notifies  = notifies;
1274
1275         info.info0 = &info0;
1276
1277         status = dcerpc_spoolss_RouterReplyPrinterEx(
1278                                 prn_hnd->notify.cli_chan->binding_handle,
1279                                 mem_ctx,
1280                                 &prn_hnd->notify.cli_hnd,
1281                                 prn_hnd->notify.change, /* color */
1282                                 prn_hnd->notify.flags,
1283                                 &reply_result,
1284                                 0, /* reply_type, must be 0 */
1285                                 info, &werr);
1286         if (!NT_STATUS_IS_OK(status)) {
1287                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1288                           "failed: %s\n",
1289                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1290                           nt_errstr(status)));
1291                 werr = ntstatus_to_werror(status);
1292         } else if (!W_ERROR_IS_OK(werr)) {
1293                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1294                           "failed: %s\n",
1295                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296                           win_errstr(werr)));
1297         }
1298         switch (reply_result) {
1299         case 0:
1300                 break;
1301         case PRINTER_NOTIFY_INFO_DISCARDED:
1302         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1303         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1304                 break;
1305         default:
1306                 break;
1307         }
1308
1309         return 0;
1310 }
1311
1312 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1313 {
1314         struct printer_handle    *p;
1315         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1316         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1317         int ret;
1318
1319         if ( !msg_group ) {
1320                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1321                 return;
1322         }
1323
1324         if (!msg_group->msgs) {
1325                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1326                 return;
1327         }
1328
1329         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1330
1331         /* loop over all printers */
1332
1333         for (p = printers_list; p; p = p->next) {
1334                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1335                 if (ret) {
1336                         goto done;
1337                 }
1338         }
1339
1340 done:
1341         DEBUG(8,("send_notify2_changes: Exit...\n"));
1342         return;
1343 }
1344
1345 /***********************************************************************
1346  **********************************************************************/
1347
1348 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1349 {
1350
1351         uint32_t tv_sec, tv_usec;
1352         size_t offset = 0;
1353
1354         /* Unpack message */
1355
1356         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1357                              msg->printer);
1358
1359         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1360                                 &tv_sec, &tv_usec,
1361                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1362
1363         if (msg->len == 0)
1364                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1365                            &msg->notify.value[0], &msg->notify.value[1]);
1366         else
1367                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1368                            &msg->len, &msg->notify.data);
1369
1370         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1371                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1372
1373         tv->tv_sec = tv_sec;
1374         tv->tv_usec = tv_usec;
1375
1376         if (msg->len == 0)
1377                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1378                           msg->notify.value[1]));
1379         else
1380                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1381
1382         return true;
1383 }
1384
1385 /********************************************************************
1386  Receive a notify2 message list
1387  ********************************************************************/
1388
1389 static void receive_notify2_message_list(struct messaging_context *msg,
1390                                          void *private_data,
1391                                          uint32_t msg_type,
1392                                          struct server_id server_id,
1393                                          DATA_BLOB *data)
1394 {
1395         size_t                  msg_count, i;
1396         char                    *buf = (char *)data->data;
1397         char                    *msg_ptr;
1398         size_t                  msg_len;
1399         SPOOLSS_NOTIFY_MSG      notify;
1400         SPOOLSS_NOTIFY_MSG_CTR  messages;
1401         int                     num_groups;
1402
1403         if (data->length < 4) {
1404                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1405                 return;
1406         }
1407
1408         msg_count = IVAL(buf, 0);
1409         msg_ptr = buf + 4;
1410
1411         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1412
1413         if (msg_count == 0) {
1414                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1415                 return;
1416         }
1417
1418         /* initialize the container */
1419
1420         ZERO_STRUCT( messages );
1421         notify_msg_ctr_init( &messages );
1422
1423         /*
1424          * build message groups for each printer identified
1425          * in a change_notify msg.  Remember that a PCN message
1426          * includes the handle returned for the srv_spoolss_replyopenprinter()
1427          * call.  Therefore messages are grouped according to printer handle.
1428          */
1429
1430         for ( i=0; i<msg_count; i++ ) {
1431                 struct timeval msg_tv;
1432
1433                 if (msg_ptr + 4 - buf > data->length) {
1434                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1435                         return;
1436                 }
1437
1438                 msg_len = IVAL(msg_ptr,0);
1439                 msg_ptr += 4;
1440
1441                 if (msg_ptr + msg_len - buf > data->length) {
1442                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1443                         return;
1444                 }
1445
1446                 /* unpack messages */
1447
1448                 ZERO_STRUCT( notify );
1449                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1450                 msg_ptr += msg_len;
1451
1452                 /* add to correct list in container */
1453
1454                 notify_msg_ctr_addmsg( &messages, &notify );
1455
1456                 /* free memory that might have been allocated by notify2_unpack_msg() */
1457
1458                 if ( notify.len != 0 )
1459                         SAFE_FREE( notify.notify.data );
1460         }
1461
1462         /* process each group of messages */
1463
1464         num_groups = notify_msg_ctr_numgroups( &messages );
1465         for ( i=0; i<num_groups; i++ )
1466                 send_notify2_changes( &messages, i );
1467
1468
1469         /* cleanup */
1470
1471         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1472                 (uint32_t)msg_count ));
1473
1474         notify_msg_ctr_destroy( &messages );
1475
1476         return;
1477 }
1478
1479 /********************************************************************
1480  Send a message to ourself about new driver being installed
1481  so we can upgrade the information for each printer bound to this
1482  driver
1483  ********************************************************************/
1484
1485 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1486                                             struct messaging_context *msg_ctx)
1487 {
1488         int len = strlen(drivername);
1489
1490         if (!len)
1491                 return false;
1492
1493         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494                 drivername));
1495
1496         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1497                            MSG_PRINTER_DRVUPGRADE,
1498                            (uint8_t *)drivername, len+1);
1499
1500         return true;
1501 }
1502
1503 void srv_spoolss_cleanup(void)
1504 {
1505         struct printer_session_counter *session_counter;
1506
1507         for (session_counter = counter_list;
1508              session_counter != NULL;
1509              session_counter = counter_list) {
1510                 DLIST_REMOVE(counter_list, session_counter);
1511                 TALLOC_FREE(session_counter);
1512         }
1513 }
1514
1515 /**********************************************************************
1516  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1517  over all printers, upgrading ones as necessary
1518  **********************************************************************/
1519
1520 void do_drv_upgrade_printer(struct messaging_context *msg,
1521                             void *private_data,
1522                             uint32_t msg_type,
1523                             struct server_id server_id,
1524                             DATA_BLOB *data)
1525 {
1526         TALLOC_CTX *tmp_ctx;
1527         struct auth_serversupplied_info *session_info = NULL;
1528         struct spoolss_PrinterInfo2 *pinfo2;
1529         NTSTATUS status;
1530         WERROR result;
1531         const char *drivername;
1532         int snum;
1533         int n_services = lp_numservices();
1534
1535         tmp_ctx = talloc_new(NULL);
1536         if (!tmp_ctx) return;
1537
1538         status = make_session_info_system(tmp_ctx, &session_info);
1539         if (!NT_STATUS_IS_OK(status)) {
1540                 DEBUG(0, ("do_drv_upgrade_printer: "
1541                           "Could not create system session_info\n"));
1542                 goto done;
1543         }
1544
1545         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1546         if (!drivername) {
1547                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1548                 goto done;
1549         }
1550
1551         DEBUG(10, ("do_drv_upgrade_printer: "
1552                    "Got message for new driver [%s]\n", drivername));
1553
1554         /* Iterate the printer list */
1555
1556         for (snum = 0; snum < n_services; snum++) {
1557                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1558                         continue;
1559                 }
1560
1561                 /* ignore [printers] share */
1562                 if (strequal(lp_const_servicename(snum), "printers")) {
1563                         continue;
1564                 }
1565
1566                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1567                                             lp_const_servicename(snum),
1568                                             &pinfo2);
1569
1570                 if (!W_ERROR_IS_OK(result)) {
1571                         continue;
1572                 }
1573
1574                 if (!pinfo2->drivername) {
1575                         continue;
1576                 }
1577
1578                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1579                         continue;
1580                 }
1581
1582                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1583
1584                 /* all we care about currently is the change_id */
1585                 result = winreg_printer_update_changeid(tmp_ctx,
1586                                                         session_info,
1587                                                         msg,
1588                                                         pinfo2->printername);
1589
1590                 if (!W_ERROR_IS_OK(result)) {
1591                         DEBUG(3, ("do_drv_upgrade_printer: "
1592                                   "Failed to update changeid [%s]\n",
1593                                   win_errstr(result)));
1594                 }
1595         }
1596
1597         /* all done */
1598 done:
1599         talloc_free(tmp_ctx);
1600 }
1601
1602 /********************************************************************
1603  Update the cache for all printq's with a registered client
1604  connection
1605  ********************************************************************/
1606
1607 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1608 {
1609         struct printer_handle *printer = printers_list;
1610         int snum;
1611
1612         /* loop through all printers and update the cache where
1613            a client is connected */
1614         while (printer) {
1615                 if ((printer->printer_type == SPLHND_PRINTER) &&
1616                     ((printer->notify.cli_chan != NULL) &&
1617                      (printer->notify.cli_chan->active_connections > 0))) {
1618                         snum = print_queue_snum(printer->sharename);
1619                         print_queue_status(msg_ctx, snum, NULL, NULL);
1620                 }
1621
1622                 printer = printer->next;
1623         }
1624
1625         return;
1626 }
1627
1628 /****************************************************************
1629  _spoolss_OpenPrinter
1630 ****************************************************************/
1631
1632 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1633                             struct spoolss_OpenPrinter *r)
1634 {
1635         struct spoolss_OpenPrinterEx e;
1636         WERROR werr;
1637
1638         ZERO_STRUCT(e.in.userlevel);
1639
1640         e.in.printername        = r->in.printername;
1641         e.in.datatype           = r->in.datatype;
1642         e.in.devmode_ctr        = r->in.devmode_ctr;
1643         e.in.access_mask        = r->in.access_mask;
1644         e.in.level              = 0;
1645
1646         e.out.handle            = r->out.handle;
1647
1648         werr = _spoolss_OpenPrinterEx(p, &e);
1649
1650         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1651                 /* OpenPrinterEx returns this for a bad
1652                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1653                  * instead.
1654                  */
1655                 werr = WERR_INVALID_PRINTER_NAME;
1656         }
1657
1658         return werr;
1659 }
1660
1661 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1662                               struct spoolss_DeviceMode *orig,
1663                               struct spoolss_DeviceMode **dest)
1664 {
1665         struct spoolss_DeviceMode *dm;
1666
1667         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1668         if (!dm) {
1669                 return WERR_NOMEM;
1670         }
1671
1672         /* copy all values, then duplicate strings and structs */
1673         *dm = *orig;
1674
1675         dm->devicename = talloc_strdup(dm, orig->devicename);
1676         if (!dm->devicename) {
1677                 return WERR_NOMEM;
1678         }
1679         dm->formname = talloc_strdup(dm, orig->formname);
1680         if (!dm->formname) {
1681                 return WERR_NOMEM;
1682         }
1683         if (orig->driverextra_data.data) {
1684                 dm->driverextra_data.data =
1685                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1686                                         orig->driverextra_data.length);
1687                 if (!dm->driverextra_data.data) {
1688                         return WERR_NOMEM;
1689                 }
1690         }
1691
1692         *dest = dm;
1693         return WERR_OK;
1694 }
1695
1696 /****************************************************************
1697  _spoolss_OpenPrinterEx
1698 ****************************************************************/
1699
1700 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1701                               struct spoolss_OpenPrinterEx *r)
1702 {
1703         int snum;
1704         struct printer_handle *Printer=NULL;
1705         WERROR result;
1706
1707         if (!r->in.printername) {
1708                 return WERR_INVALID_PARAM;
1709         }
1710
1711         if (r->in.level < 0 || r->in.level > 3) {
1712                 return WERR_INVALID_PARAM;
1713         }
1714         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1715             (r->in.level == 2 && !r->in.userlevel.level2) ||
1716             (r->in.level == 3 && !r->in.userlevel.level3)) {
1717                 return WERR_INVALID_PARAM;
1718         }
1719
1720         /* some sanity check because you can open a printer or a print server */
1721         /* aka: \\server\printer or \\server */
1722
1723         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1724
1725         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1726         if (!W_ERROR_IS_OK(result)) {
1727                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1728                         "for printer %s\n", r->in.printername));
1729                 ZERO_STRUCTP(r->out.handle);
1730                 return result;
1731         }
1732
1733         Printer = find_printer_index_by_hnd(p, r->out.handle);
1734         if ( !Printer ) {
1735                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1736                         "handle we created for printer %s\n", r->in.printername));
1737                 close_printer_handle(p, r->out.handle);
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_INVALID_PARAM;
1740         }
1741
1742         /*
1743          * First case: the user is opening the print server:
1744          *
1745          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1746          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1747          *
1748          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1749          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1750          * or if the user is listed in the smb.conf printer admin parameter.
1751          *
1752          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1753          * client view printer folder, but does not show the MSAPW.
1754          *
1755          * Note: this test needs code to check access rights here too. Jeremy
1756          * could you look at this?
1757          *
1758          * Second case: the user is opening a printer:
1759          * NT doesn't let us connect to a printer if the connecting user
1760          * doesn't have print permission.
1761          *
1762          * Third case: user is opening a Port Monitor
1763          * access checks same as opening a handle to the print server.
1764          */
1765
1766         switch (Printer->printer_type )
1767         {
1768         case SPLHND_SERVER:
1769         case SPLHND_PORTMON_TCP:
1770         case SPLHND_PORTMON_LOCAL:
1771                 /* Printserver handles use global struct... */
1772
1773                 snum = -1;
1774
1775                 /* Map standard access rights to object specific access rights */
1776
1777                 se_map_standard(&r->in.access_mask,
1778                                 &printserver_std_mapping);
1779
1780                 /* Deny any object specific bits that don't apply to print
1781                    servers (i.e printer and job specific bits) */
1782
1783                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1784
1785                 if (r->in.access_mask &
1786                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1787                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1788                         close_printer_handle(p, r->out.handle);
1789                         ZERO_STRUCTP(r->out.handle);
1790                         return WERR_ACCESS_DENIED;
1791                 }
1792
1793                 /* Allow admin access */
1794
1795                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1796                 {
1797                         if (!lp_ms_add_printer_wizard()) {
1798                                 close_printer_handle(p, r->out.handle);
1799                                 ZERO_STRUCTP(r->out.handle);
1800                                 return WERR_ACCESS_DENIED;
1801                         }
1802
1803                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1804                            and not a printer admin, then fail */
1805
1806                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1807                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1808                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1809                             !token_contains_name_in_list(
1810                                     uidtoname(p->session_info->utok.uid),
1811                                     p->session_info->info3->base.domain.string,
1812                                     NULL,
1813                                     p->session_info->security_token,
1814                                     lp_printer_admin(snum))) {
1815                                 close_printer_handle(p, r->out.handle);
1816                                 ZERO_STRUCTP(r->out.handle);
1817                                 DEBUG(3,("access DENIED as user is not root, "
1818                                         "has no printoperator privilege, "
1819                                         "not a member of the printoperator builtin group and "
1820                                         "is not in printer admin list"));
1821                                 return WERR_ACCESS_DENIED;
1822                         }
1823
1824                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1825                 }
1826                 else
1827                 {
1828                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1829                 }
1830
1831                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1832                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1833
1834                 /* We fall through to return WERR_OK */
1835                 break;
1836
1837         case SPLHND_PRINTER:
1838                 /* NT doesn't let us connect to a printer if the connecting user
1839                    doesn't have print permission.  */
1840
1841                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1842                         close_printer_handle(p, r->out.handle);
1843                         ZERO_STRUCTP(r->out.handle);
1844                         return WERR_BADFID;
1845                 }
1846
1847                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1848                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1849                 }
1850
1851                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1852
1853                 /* map an empty access mask to the minimum access mask */
1854                 if (r->in.access_mask == 0x0)
1855                         r->in.access_mask = PRINTER_ACCESS_USE;
1856
1857                 /*
1858                  * If we are not serving the printer driver for this printer,
1859                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1860                  * will keep NT clients happy  --jerry
1861                  */
1862
1863                 if (lp_use_client_driver(snum)
1864                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1865                 {
1866                         r->in.access_mask = PRINTER_ACCESS_USE;
1867                 }
1868
1869                 /* check smb.conf parameters and the the sec_desc */
1870
1871                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1872                                   p->client_id->name, p->client_id->addr)) {
1873                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1874                         ZERO_STRUCTP(r->out.handle);
1875                         return WERR_ACCESS_DENIED;
1876                 }
1877
1878                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1879                                    p->session_info->security_token, snum) ||
1880                     !print_access_check(p->session_info,
1881                                         p->msg_ctx,
1882                                         snum,
1883                                         r->in.access_mask)) {
1884                         DEBUG(3, ("access DENIED for printer open\n"));
1885                         close_printer_handle(p, r->out.handle);
1886                         ZERO_STRUCTP(r->out.handle);
1887                         return WERR_ACCESS_DENIED;
1888                 }
1889
1890                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1891                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1892                         close_printer_handle(p, r->out.handle);
1893                         ZERO_STRUCTP(r->out.handle);
1894                         return WERR_ACCESS_DENIED;
1895                 }
1896
1897                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1898                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1899                 else
1900                         r->in.access_mask = PRINTER_ACCESS_USE;
1901
1902                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1903                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1904
1905                 winreg_create_printer(p->mem_ctx,
1906                                       get_session_info_system(),
1907                                       p->msg_ctx,
1908                                       lp_const_servicename(snum));
1909
1910                 break;
1911
1912         default:
1913                 /* sanity check to prevent programmer error */
1914                 ZERO_STRUCTP(r->out.handle);
1915                 return WERR_BADFID;
1916         }
1917
1918         Printer->access_granted = r->in.access_mask;
1919
1920         /*
1921          * If the client sent a devmode in the OpenPrinter() call, then
1922          * save it here in case we get a job submission on this handle
1923          */
1924
1925          if ((Printer->printer_type != SPLHND_SERVER) &&
1926              r->in.devmode_ctr.devmode) {
1927                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1928                                 &Printer->devmode);
1929          }
1930
1931 #if 0   /* JERRY -- I'm doubtful this is really effective */
1932         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1933            optimization in Windows 2000 clients  --jerry */
1934
1935         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1936                 && (RA_WIN2K == get_remote_arch()) )
1937         {
1938                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1939                 sys_usleep( 500000 );
1940         }
1941 #endif
1942
1943         return WERR_OK;
1944 }
1945
1946 /****************************************************************
1947  _spoolss_ClosePrinter
1948 ****************************************************************/
1949
1950 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1951                              struct spoolss_ClosePrinter *r)
1952 {
1953         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1954
1955         if (Printer && Printer->document_started) {
1956                 struct spoolss_EndDocPrinter e;
1957
1958                 e.in.handle = r->in.handle;
1959
1960                 _spoolss_EndDocPrinter(p, &e);
1961         }
1962
1963         if (!close_printer_handle(p, r->in.handle))
1964                 return WERR_BADFID;
1965
1966         /* clear the returned printer handle.  Observed behavior
1967            from Win2k server.  Don't think this really matters.
1968            Previous code just copied the value of the closed
1969            handle.    --jerry */
1970
1971         ZERO_STRUCTP(r->out.handle);
1972
1973         return WERR_OK;
1974 }
1975
1976 /****************************************************************
1977  _spoolss_DeletePrinter
1978 ****************************************************************/
1979
1980 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1981                               struct spoolss_DeletePrinter *r)
1982 {
1983         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1984         WERROR result;
1985         int snum;
1986
1987         if (Printer && Printer->document_started) {
1988                 struct spoolss_EndDocPrinter e;
1989
1990                 e.in.handle = r->in.handle;
1991
1992                 _spoolss_EndDocPrinter(p, &e);
1993         }
1994
1995         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1996                 winreg_delete_printer_key(p->mem_ctx,
1997                                           get_session_info_system(),
1998                                           p->msg_ctx,
1999                                           lp_const_servicename(snum),
2000                                           "");
2001         }
2002
2003         result = delete_printer_handle(p, r->in.handle);
2004
2005         return result;
2006 }
2007
2008 /*******************************************************************
2009  * static function to lookup the version id corresponding to an
2010  * long architecture string
2011  ******************************************************************/
2012
2013 static const struct print_architecture_table_node archi_table[]= {
2014
2015         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2016         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2017         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2018         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2019         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2020         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2021         {"Windows x64",          SPL_ARCH_X64,          3 },
2022         {NULL,                   "",            -1 }
2023 };
2024
2025 static int get_version_id(const char *arch)
2026 {
2027         int i;
2028
2029         for (i=0; archi_table[i].long_archi != NULL; i++)
2030         {
2031                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2032                         return (archi_table[i].version);
2033         }
2034
2035         return -1;
2036 }
2037
2038 /****************************************************************
2039  _spoolss_DeletePrinterDriver
2040 ****************************************************************/
2041
2042 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2043                                     struct spoolss_DeletePrinterDriver *r)
2044 {
2045
2046         struct spoolss_DriverInfo8 *info = NULL;
2047         struct spoolss_DriverInfo8 *info_win2k = NULL;
2048         int                             version;
2049         WERROR                          status;
2050
2051         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2052            and not a printer admin, then fail */
2053
2054         if ( (p->session_info->utok.uid != sec_initial_uid())
2055              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2056                 && !token_contains_name_in_list(
2057                         uidtoname(p->session_info->utok.uid),
2058                         p->session_info->info3->base.domain.string,
2059                         NULL,
2060                         p->session_info->security_token,
2061                         lp_printer_admin(-1)) )
2062         {
2063                 return WERR_ACCESS_DENIED;
2064         }
2065
2066         /* check that we have a valid driver name first */
2067
2068         if ((version = get_version_id(r->in.architecture)) == -1)
2069                 return WERR_INVALID_ENVIRONMENT;
2070
2071         status = winreg_get_driver(p->mem_ctx,
2072                                    get_session_info_system(),
2073                                    p->msg_ctx,
2074                                    r->in.architecture, r->in.driver,
2075                                    version, &info);
2076         if (!W_ERROR_IS_OK(status)) {
2077                 /* try for Win2k driver if "Windows NT x86" */
2078
2079                 if ( version == 2 ) {
2080                         version = 3;
2081
2082                         status = winreg_get_driver(p->mem_ctx,
2083                                                    get_session_info_system(),
2084                                                    p->msg_ctx,
2085                                                    r->in.architecture,
2086                                                    r->in.driver,
2087                                                    version, &info);
2088                         if (!W_ERROR_IS_OK(status)) {
2089                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2090                                 goto done;
2091                         }
2092                 }
2093                 /* otherwise it was a failure */
2094                 else {
2095                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2096                         goto done;
2097                 }
2098
2099         }
2100
2101         if (printer_driver_in_use(p->mem_ctx,
2102                                   get_session_info_system(),
2103                                   p->msg_ctx,
2104                                   info)) {
2105                 status = WERR_PRINTER_DRIVER_IN_USE;
2106                 goto done;
2107         }
2108
2109         if (version == 2) {
2110                 status = winreg_get_driver(p->mem_ctx,
2111                                            get_session_info_system(),
2112                                            p->msg_ctx,
2113                                            r->in.architecture,
2114                                            r->in.driver, 3, &info_win2k);
2115                 if (W_ERROR_IS_OK(status)) {
2116                         /* if we get to here, we now have 2 driver info structures to remove */
2117                         /* remove the Win2k driver first*/
2118
2119                         status = winreg_del_driver(p->mem_ctx,
2120                                                    get_session_info_system(),
2121                                                    p->msg_ctx,
2122                                                    info_win2k, 3);
2123                         talloc_free(info_win2k);
2124
2125                         /* this should not have failed---if it did, report to client */
2126                         if (!W_ERROR_IS_OK(status)) {
2127                                 goto done;
2128                         }
2129                 }
2130         }
2131
2132         status = winreg_del_driver(p->mem_ctx,
2133                                    get_session_info_system(),
2134                                    p->msg_ctx,
2135                                    info, version);
2136
2137 done:
2138         talloc_free(info);
2139
2140         return status;
2141 }
2142
2143 /****************************************************************
2144  _spoolss_DeletePrinterDriverEx
2145 ****************************************************************/
2146
2147 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2148                                       struct spoolss_DeletePrinterDriverEx *r)
2149 {
2150         struct spoolss_DriverInfo8      *info = NULL;
2151         struct spoolss_DriverInfo8      *info_win2k = NULL;
2152         int                             version;
2153         bool                            delete_files;
2154         WERROR                          status;
2155
2156         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2157            and not a printer admin, then fail */
2158
2159         if ( (p->session_info->utok.uid != sec_initial_uid())
2160                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2161                 && !token_contains_name_in_list(
2162                         uidtoname(p->session_info->utok.uid),
2163                         p->session_info->info3->base.domain.string,
2164                         NULL,
2165                         p->session_info->security_token, lp_printer_admin(-1)) )
2166         {
2167                 return WERR_ACCESS_DENIED;
2168         }
2169
2170         /* check that we have a valid driver name first */
2171         if ((version = get_version_id(r->in.architecture)) == -1) {
2172                 /* this is what NT returns */
2173                 return WERR_INVALID_ENVIRONMENT;
2174         }
2175
2176         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2177                 version = r->in.version;
2178
2179         status = winreg_get_driver(p->mem_ctx,
2180                                    get_session_info_system(),
2181                                    p->msg_ctx,
2182                                    r->in.architecture,
2183                                    r->in.driver,
2184                                    version,
2185                                    &info);
2186         if (!W_ERROR_IS_OK(status)) {
2187                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2188
2189                 /*
2190                  * if the client asked for a specific version,
2191                  * or this is something other than Windows NT x86,
2192                  * then we've failed
2193                  */
2194
2195                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2196                         goto done;
2197
2198                 /* try for Win2k driver if "Windows NT x86" */
2199
2200                 version = 3;
2201                 status = winreg_get_driver(info,
2202                                            get_session_info_system(),
2203                                            p->msg_ctx,
2204                                            r->in.architecture,
2205                                            r->in.driver,
2206                                            version, &info);
2207                 if (!W_ERROR_IS_OK(status)) {
2208                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2209                         goto done;
2210                 }
2211         }
2212
2213         if (printer_driver_in_use(info,
2214                                   get_session_info_system(),
2215                                   p->msg_ctx,
2216                                   info)) {
2217                 status = WERR_PRINTER_DRIVER_IN_USE;
2218                 goto done;
2219         }
2220
2221         /*
2222          * we have a couple of cases to consider.
2223          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2224          *     then the delete should fail if **any** files overlap with
2225          *     other drivers
2226          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2227          *     non-overlapping files
2228          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2229          *     is set, the do not delete any files
2230          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2231          */
2232
2233         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2234
2235         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2236
2237         if (delete_files &&
2238             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2239             printer_driver_files_in_use(info,
2240                                         get_session_info_system(),
2241                                         p->msg_ctx,
2242                                         info)) {
2243                 /* no idea of the correct error here */
2244                 status = WERR_ACCESS_DENIED;
2245                 goto done;
2246         }
2247
2248
2249         /* also check for W32X86/3 if necessary; maybe we already have? */
2250
2251         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2252                 status = winreg_get_driver(info,
2253                                            get_session_info_system(),
2254                                            p->msg_ctx,
2255                                            r->in.architecture,
2256                                            r->in.driver, 3, &info_win2k);
2257                 if (W_ERROR_IS_OK(status)) {
2258
2259                         if (delete_files &&
2260                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2261                             printer_driver_files_in_use(info,
2262                                                         get_session_info_system(),
2263                                                         p->msg_ctx,
2264                                                         info_win2k)) {
2265                                 /* no idea of the correct error here */
2266                                 talloc_free(info_win2k);
2267                                 status = WERR_ACCESS_DENIED;
2268                                 goto done;
2269                         }
2270
2271                         /* if we get to here, we now have 2 driver info structures to remove */
2272                         /* remove the Win2k driver first*/
2273
2274                         status = winreg_del_driver(info,
2275                                                    get_session_info_system(),
2276                                                    p->msg_ctx,
2277                                                    info_win2k,
2278                                                    3);
2279
2280                         /* this should not have failed---if it did, report to client */
2281
2282                         if (!W_ERROR_IS_OK(status)) {
2283                                 goto done;
2284                         }
2285
2286                         /*
2287                          * now delete any associated files if delete_files is
2288                          * true. Even if this part failes, we return succes
2289                          * because the driver doesn not exist any more
2290                          */
2291                         if (delete_files) {
2292                                 delete_driver_files(get_session_info_system(),
2293                                                     info_win2k);
2294                         }
2295                 }
2296         }
2297
2298         status = winreg_del_driver(info,
2299                                    get_session_info_system(),
2300                                    p->msg_ctx,
2301                                    info,
2302                                    version);
2303         if (!W_ERROR_IS_OK(status)) {
2304                 goto done;
2305         }
2306
2307         /*
2308          * now delete any associated files if delete_files is
2309          * true. Even if this part failes, we return succes
2310          * because the driver doesn not exist any more
2311          */
2312         if (delete_files) {
2313                 delete_driver_files(get_session_info_system(), info);
2314         }
2315
2316 done:
2317         talloc_free(info);
2318         return status;
2319 }
2320
2321
2322 /********************************************************************
2323  GetPrinterData on a printer server Handle.
2324 ********************************************************************/
2325
2326 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2327                                             const char *value,
2328                                             enum winreg_Type *type,
2329                                             union spoolss_PrinterData *data)
2330 {
2331         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2332
2333         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2334                 *type = REG_DWORD;
2335                 data->value = 0x00;
2336                 return WERR_OK;
2337         }
2338
2339         if (!StrCaseCmp(value, "BeepEnabled")) {
2340                 *type = REG_DWORD;
2341                 data->value = 0x00;
2342                 return WERR_OK;
2343         }
2344
2345         if (!StrCaseCmp(value, "EventLog")) {
2346                 *type = REG_DWORD;
2347                 /* formally was 0x1b */
2348                 data->value = 0x00;
2349                 return WERR_OK;
2350         }
2351
2352         if (!StrCaseCmp(value, "NetPopup")) {
2353                 *type = REG_DWORD;
2354                 data->value = 0x00;
2355                 return WERR_OK;
2356         }
2357
2358         if (!StrCaseCmp(value, "MajorVersion")) {
2359                 *type = REG_DWORD;
2360
2361                 /* Windows NT 4.0 seems to not allow uploading of drivers
2362                    to a server that reports 0x3 as the MajorVersion.
2363                    need to investigate more how Win2k gets around this .
2364                    -- jerry */
2365
2366                 if (RA_WINNT == get_remote_arch()) {
2367                         data->value = 0x02;
2368                 } else {
2369                         data->value = 0x03;
2370                 }
2371
2372                 return WERR_OK;
2373         }
2374
2375         if (!StrCaseCmp(value, "MinorVersion")) {
2376                 *type = REG_DWORD;
2377                 data->value = 0x00;
2378                 return WERR_OK;
2379         }
2380
2381         /* REG_BINARY
2382          *  uint32_t size        = 0x114
2383          *  uint32_t major       = 5
2384          *  uint32_t minor       = [0|1]
2385          *  uint32_t build       = [2195|2600]
2386          *  extra unicode string = e.g. "Service Pack 3"
2387          */
2388         if (!StrCaseCmp(value, "OSVersion")) {
2389                 DATA_BLOB blob;
2390                 enum ndr_err_code ndr_err;
2391                 struct spoolss_OSVersion os;
2392
2393                 os.major                = 5;    /* Windows 2000 == 5.0 */
2394                 os.minor                = 0;
2395                 os.build                = 2195; /* build */
2396                 os.extra_string         = "";   /* leave extra string empty */
2397
2398                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2399                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2400                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2401                         return WERR_GENERAL_FAILURE;
2402                 }
2403
2404                 *type = REG_BINARY;
2405                 data->binary = blob;
2406
2407                 return WERR_OK;
2408         }
2409
2410
2411         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2412                 *type = REG_SZ;
2413
2414                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2415                 W_ERROR_HAVE_NO_MEMORY(data->string);
2416
2417                 return WERR_OK;
2418         }
2419
2420         if (!StrCaseCmp(value, "Architecture")) {
2421                 *type = REG_SZ;
2422                 data->string = talloc_strdup(mem_ctx,
2423                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2424                 W_ERROR_HAVE_NO_MEMORY(data->string);
2425
2426                 return WERR_OK;
2427         }
2428
2429         if (!StrCaseCmp(value, "DsPresent")) {
2430                 *type = REG_DWORD;
2431
2432                 /* only show the publish check box if we are a
2433                    member of a AD domain */
2434
2435                 if (lp_security() == SEC_ADS) {
2436                         data->value = 0x01;
2437                 } else {
2438                         data->value = 0x00;
2439                 }
2440                 return WERR_OK;
2441         }
2442
2443         if (!StrCaseCmp(value, "DNSMachineName")) {
2444                 const char *hostname = get_mydnsfullname();
2445
2446                 if (!hostname) {
2447                         return WERR_BADFILE;
2448                 }
2449
2450                 *type = REG_SZ;
2451                 data->string = talloc_strdup(mem_ctx, hostname);
2452                 W_ERROR_HAVE_NO_MEMORY(data->string);
2453
2454                 return WERR_OK;
2455         }
2456
2457         *type = REG_NONE;
2458
2459         return WERR_INVALID_PARAM;
2460 }
2461
2462 /****************************************************************
2463  _spoolss_GetPrinterData
2464 ****************************************************************/
2465
2466 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2467                                struct spoolss_GetPrinterData *r)
2468 {
2469         struct spoolss_GetPrinterDataEx r2;
2470
2471         r2.in.handle            = r->in.handle;
2472         r2.in.key_name          = "PrinterDriverData";
2473         r2.in.value_name        = r->in.value_name;
2474         r2.in.offered           = r->in.offered;
2475         r2.out.type             = r->out.type;
2476         r2.out.data             = r->out.data;
2477         r2.out.needed           = r->out.needed;
2478
2479         return _spoolss_GetPrinterDataEx(p, &r2);
2480 }
2481
2482 /*********************************************************
2483  Connect to the client machine.
2484 **********************************************************/
2485
2486 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2487                         struct sockaddr_storage *client_ss, const char *remote_machine)
2488 {
2489         NTSTATUS ret;
2490         struct cli_state *the_cli;
2491         struct sockaddr_storage rm_addr;
2492         char addr[INET6_ADDRSTRLEN];
2493
2494         if ( is_zero_addr(client_ss) ) {
2495                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2496                         remote_machine));
2497                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2498                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2499                         return false;
2500                 }
2501                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2502         } else {
2503                 rm_addr = *client_ss;
2504                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2505                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2506                         addr));
2507         }
2508
2509         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2510                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2511                         addr));
2512                 return false;
2513         }
2514
2515         /* setup the connection */
2516         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2517                 &rm_addr, 0, "IPC$", "IPC",
2518                 "", /* username */
2519                 "", /* domain */
2520                 "", /* password */
2521                 0, lp_client_signing());
2522
2523         if ( !NT_STATUS_IS_OK( ret ) ) {
2524                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2525                         remote_machine ));
2526                 return false;
2527         }
2528
2529         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2530                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2531                 cli_shutdown(the_cli);
2532                 return false;
2533         }
2534
2535         /*
2536          * Ok - we have an anonymous connection to the IPC$ share.
2537          * Now start the NT Domain stuff :-).
2538          */
2539
2540         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2541         if (!NT_STATUS_IS_OK(ret)) {
2542                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2543                         remote_machine, nt_errstr(ret)));
2544                 cli_shutdown(the_cli);
2545                 return false;
2546         }
2547
2548         return true;
2549 }
2550
2551 /***************************************************************************
2552  Connect to the client.
2553 ****************************************************************************/
2554
2555 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2556                                         uint32_t localprinter,
2557                                         enum winreg_Type type,
2558                                         struct policy_handle *handle,
2559                                         struct notify_back_channel **_chan,
2560                                         struct sockaddr_storage *client_ss,
2561                                         struct messaging_context *msg_ctx)
2562 {
2563         WERROR result;
2564         NTSTATUS status;
2565         struct notify_back_channel *chan;
2566
2567         for (chan = back_channels; chan; chan = chan->next) {
2568                 if (memcmp(&chan->client_address, client_ss,
2569                            sizeof(struct sockaddr_storage)) == 0) {
2570                         break;
2571                 }
2572         }
2573
2574         /*
2575          * If it's the first connection, contact the client
2576          * and connect to the IPC$ share anonymously
2577          */
2578         if (!chan) {
2579                 fstring unix_printer;
2580
2581                 /* the +2 is to strip the leading 2 backslashs */
2582                 fstrcpy(unix_printer, printer + 2);
2583
2584                 chan = talloc_zero(back_channels, struct notify_back_channel);
2585                 if (!chan) {
2586                         return false;
2587                 }
2588                 chan->client_address = *client_ss;
2589
2590                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2591                         TALLOC_FREE(chan);
2592                         return false;
2593                 }
2594                 chan->binding_handle = chan->cli_pipe->binding_handle;
2595
2596                 DLIST_ADD(back_channels, chan);
2597
2598                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2599                                    receive_notify2_message_list);
2600                 /* Tell the connections db we're now interested in printer
2601                  * notify messages. */
2602                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2603                                             true, FLAG_MSG_PRINT_NOTIFY);
2604         }
2605
2606         /*
2607          * Tell the specific printing tdb we want messages for this printer
2608          * by registering our PID.
2609          */
2610
2611         if (!print_notify_register_pid(snum)) {
2612                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2613                           printer));
2614         }
2615
2616         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2617                                                  talloc_tos(),
2618                                                  printer,
2619                                                  localprinter,
2620                                                  type,
2621                                                  0,
2622                                                  NULL,
2623                                                  handle,
2624                                                  &result);
2625         if (!NT_STATUS_IS_OK(status)) {
2626                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2627                 result = ntstatus_to_werror(status);
2628         } else if (!W_ERROR_IS_OK(result)) {
2629                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2630         }
2631
2632         chan->active_connections++;
2633         *_chan = chan;
2634
2635         return (W_ERROR_IS_OK(result));
2636 }
2637
2638 /****************************************************************
2639  ****************************************************************/
2640
2641 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2642                                                              const struct spoolss_NotifyOption *r)
2643 {
2644         struct spoolss_NotifyOption *option;
2645         uint32_t i,k;
2646
2647         if (!r) {
2648                 return NULL;
2649         }
2650
2651         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2652         if (!option) {
2653                 return NULL;
2654         }
2655
2656         *option = *r;
2657
2658         if (!option->count) {
2659                 return option;
2660         }
2661
2662         option->types = talloc_zero_array(option,
2663                 struct spoolss_NotifyOptionType, option->count);
2664         if (!option->types) {
2665                 talloc_free(option);
2666                 return NULL;
2667         }
2668
2669         for (i=0; i < option->count; i++) {
2670                 option->types[i] = r->types[i];
2671
2672                 if (option->types[i].count) {
2673                         option->types[i].fields = talloc_zero_array(option,
2674                                 union spoolss_Field, option->types[i].count);
2675                         if (!option->types[i].fields) {
2676                                 talloc_free(option);
2677                                 return NULL;
2678                         }
2679                         for (k=0; k<option->types[i].count; k++) {
2680                                 option->types[i].fields[k] =
2681                                         r->types[i].fields[k];
2682                         }
2683                 }
2684         }
2685
2686         return option;
2687 }
2688
2689 /****************************************************************
2690  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2691  *
2692  * before replying OK: status=0 a rpc call is made to the workstation
2693  * asking ReplyOpenPrinter
2694  *
2695  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2696  * called from api_spoolss_rffpcnex
2697 ****************************************************************/
2698
2699 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2700                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2701 {
2702         int snum = -1;
2703         struct spoolss_NotifyOption *option = r->in.notify_options;
2704         struct sockaddr_storage client_ss;
2705
2706         /* store the notify value in the printer struct */
2707
2708         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2709
2710         if (!Printer) {
2711                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2712                         "Invalid handle (%s:%u:%u).\n",
2713                         OUR_HANDLE(r->in.handle)));
2714                 return WERR_BADFID;
2715         }
2716
2717         Printer->notify.flags           = r->in.flags;
2718         Printer->notify.options         = r->in.options;
2719         Printer->notify.printerlocal    = r->in.printer_local;
2720         Printer->notify.msg_ctx         = p->msg_ctx;
2721
2722         TALLOC_FREE(Printer->notify.option);
2723         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2724
2725         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2726
2727         /* Connect to the client machine and send a ReplyOpenPrinter */
2728
2729         if ( Printer->printer_type == SPLHND_SERVER)
2730                 snum = -1;
2731         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2732                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2733                 return WERR_BADFID;
2734
2735         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2736                 "client_address is %s\n", p->client_id->addr));
2737
2738         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2739                                    AI_NUMERICHOST)) {
2740                 return WERR_SERVER_UNAVAILABLE;
2741         }
2742
2743         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2744                                         Printer->notify.printerlocal, REG_SZ,
2745                                         &Printer->notify.cli_hnd,
2746                                         &Printer->notify.cli_chan,
2747                                         &client_ss, p->msg_ctx)) {
2748                 return WERR_SERVER_UNAVAILABLE;
2749         }
2750
2751         return WERR_OK;
2752 }
2753
2754 /*******************************************************************
2755  * fill a notify_info_data with the servername
2756  ********************************************************************/
2757
2758 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2759                                        int snum,
2760                                        struct spoolss_Notify *data,
2761                                        print_queue_struct *queue,
2762                                        struct spoolss_PrinterInfo2 *pinfo2,
2763                                        TALLOC_CTX *mem_ctx)
2764 {
2765         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2766 }
2767
2768 /*******************************************************************
2769  * fill a notify_info_data with the printername (not including the servername).
2770  ********************************************************************/
2771
2772 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2773                                         int snum,
2774                                         struct spoolss_Notify *data,
2775                                         print_queue_struct *queue,
2776                                         struct spoolss_PrinterInfo2 *pinfo2,
2777                                         TALLOC_CTX *mem_ctx)
2778 {
2779         /* the notify name should not contain the \\server\ part */
2780         const char *p = strrchr(pinfo2->printername, '\\');
2781
2782         if (!p) {
2783                 p = pinfo2->printername;
2784         } else {
2785                 p++;
2786         }
2787
2788         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the servicename
2793  ********************************************************************/
2794
2795 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2796                                       int snum,
2797                                       struct spoolss_Notify *data,
2798                                       print_queue_struct *queue,
2799                                       struct spoolss_PrinterInfo2 *pinfo2,
2800                                       TALLOC_CTX *mem_ctx)
2801 {
2802         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2803 }
2804
2805 /*******************************************************************
2806  * fill a notify_info_data with the port name
2807  ********************************************************************/
2808
2809 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2810                                      int snum,
2811                                      struct spoolss_Notify *data,
2812                                      print_queue_struct *queue,
2813                                      struct spoolss_PrinterInfo2 *pinfo2,
2814                                      TALLOC_CTX *mem_ctx)
2815 {
2816         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2817 }
2818
2819 /*******************************************************************
2820  * fill a notify_info_data with the printername
2821  * but it doesn't exist, have to see what to do
2822  ********************************************************************/
2823
2824 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2825                                        int snum,
2826                                        struct spoolss_Notify *data,
2827                                        print_queue_struct *queue,
2828                                        struct spoolss_PrinterInfo2 *pinfo2,
2829                                        TALLOC_CTX *mem_ctx)
2830 {
2831         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2832 }
2833
2834 /*******************************************************************
2835  * fill a notify_info_data with the comment
2836  ********************************************************************/
2837
2838 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2839                                    int snum,
2840                                    struct spoolss_Notify *data,
2841                                    print_queue_struct *queue,
2842                                    struct spoolss_PrinterInfo2 *pinfo2,
2843                                    TALLOC_CTX *mem_ctx)
2844 {
2845         const char *p;
2846
2847         if (*pinfo2->comment == '\0') {
2848                 p = lp_comment(snum);
2849         } else {
2850                 p = pinfo2->comment;
2851         }
2852
2853         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2854 }
2855
2856 /*******************************************************************
2857  * fill a notify_info_data with the comment
2858  * location = "Room 1, floor 2, building 3"
2859  ********************************************************************/
2860
2861 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2862                                     int snum,
2863                                     struct spoolss_Notify *data,
2864                                     print_queue_struct *queue,
2865                                     struct spoolss_PrinterInfo2 *pinfo2,
2866                                     TALLOC_CTX *mem_ctx)
2867 {
2868         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2869 }
2870
2871 /*******************************************************************
2872  * fill a notify_info_data with the device mode
2873  * jfm:xxxx don't to it for know but that's a real problem !!!
2874  ********************************************************************/
2875
2876 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2877                                    int snum,
2878                                    struct spoolss_Notify *data,
2879                                    print_queue_struct *queue,
2880                                    struct spoolss_PrinterInfo2 *pinfo2,
2881                                    TALLOC_CTX *mem_ctx)
2882 {
2883         /* for a dummy implementation we have to zero the fields */
2884         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with the separator file name
2889  ********************************************************************/
2890
2891 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2892                                    int snum,
2893                                    struct spoolss_Notify *data,
2894                                    print_queue_struct *queue,
2895                                    struct spoolss_PrinterInfo2 *pinfo2,
2896                                    TALLOC_CTX *mem_ctx)
2897 {
2898         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the print processor
2903  * jfm:xxxx return always winprint to indicate we don't do anything to it
2904  ********************************************************************/
2905
2906 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2907                                            int snum,
2908                                            struct spoolss_Notify *data,
2909                                            print_queue_struct *queue,
2910                                            struct spoolss_PrinterInfo2 *pinfo2,
2911                                            TALLOC_CTX *mem_ctx)
2912 {
2913         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2914 }
2915
2916 /*******************************************************************
2917  * fill a notify_info_data with the print processor options
2918  * jfm:xxxx send an empty string
2919  ********************************************************************/
2920
2921 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2922                                       int snum,
2923                                       struct spoolss_Notify *data,
2924                                       print_queue_struct *queue,
2925                                       struct spoolss_PrinterInfo2 *pinfo2,
2926                                       TALLOC_CTX *mem_ctx)
2927 {
2928         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2929 }
2930
2931 /*******************************************************************
2932  * fill a notify_info_data with the data type
2933  * jfm:xxxx always send RAW as data type
2934  ********************************************************************/
2935
2936 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2937                                     int snum,
2938                                     struct spoolss_Notify *data,
2939                                     print_queue_struct *queue,
2940                                     struct spoolss_PrinterInfo2 *pinfo2,
2941                                     TALLOC_CTX *mem_ctx)
2942 {
2943         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2944 }
2945
2946 /*******************************************************************
2947  * fill a notify_info_data with the security descriptor
2948  * jfm:xxxx send an null pointer to say no security desc
2949  * have to implement security before !
2950  ********************************************************************/
2951
2952 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2953                                          int snum,
2954                                          struct spoolss_Notify *data,
2955                                          print_queue_struct *queue,
2956                                          struct spoolss_PrinterInfo2 *pinfo2,
2957                                          TALLOC_CTX *mem_ctx)
2958 {
2959         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2960 }
2961
2962 /*******************************************************************
2963  * fill a notify_info_data with the attributes
2964  * jfm:xxxx a samba printer is always shared
2965  ********************************************************************/
2966
2967 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2968                                       int snum,
2969                                       struct spoolss_Notify *data,
2970                                       print_queue_struct *queue,
2971                                       struct spoolss_PrinterInfo2 *pinfo2,
2972                                       TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the priority
2979  ********************************************************************/
2980
2981 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2982                                     int snum,
2983                                     struct spoolss_Notify *data,
2984                                     print_queue_struct *queue,
2985                                     struct spoolss_PrinterInfo2 *pinfo2,
2986                                     TALLOC_CTX *mem_ctx)
2987 {
2988         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the default priority
2993  ********************************************************************/
2994
2995 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2996                                             int snum,
2997                                             struct spoolss_Notify *data,
2998                                             print_queue_struct *queue,
2999                                             struct spoolss_PrinterInfo2 *pinfo2,
3000                                             TALLOC_CTX *mem_ctx)
3001 {
3002         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the start time
3007  ********************************************************************/
3008
3009 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3010                                       int snum,
3011                                       struct spoolss_Notify *data,
3012                                       print_queue_struct *queue,
3013                                       struct spoolss_PrinterInfo2 *pinfo2,
3014                                       TALLOC_CTX *mem_ctx)
3015 {
3016         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the until time
3021  ********************************************************************/
3022
3023 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3024                                       int snum,
3025                                       struct spoolss_Notify *data,
3026                                       print_queue_struct *queue,
3027                                       struct spoolss_PrinterInfo2 *pinfo2,
3028                                       TALLOC_CTX *mem_ctx)
3029 {
3030         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3031 }
3032
3033 /*******************************************************************
3034  * fill a notify_info_data with the status
3035  ********************************************************************/
3036
3037 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3038                                   int snum,
3039                                   struct spoolss_Notify *data,
3040                                   print_queue_struct *queue,
3041                                   struct spoolss_PrinterInfo2 *pinfo2,
3042                                   TALLOC_CTX *mem_ctx)
3043 {
3044         print_status_struct status;
3045
3046         print_queue_length(msg_ctx, snum, &status);
3047         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with the number of jobs queued
3052  ********************************************************************/
3053
3054 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3055                                  int snum,
3056                                  struct spoolss_Notify *data,
3057                                  print_queue_struct *queue,
3058                                  struct spoolss_PrinterInfo2 *pinfo2,
3059                                  TALLOC_CTX *mem_ctx)
3060 {
3061         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3062                 data, print_queue_length(msg_ctx, snum, NULL));
3063 }
3064
3065 /*******************************************************************
3066  * fill a notify_info_data with the average ppm
3067  ********************************************************************/
3068
3069 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3070                                        int snum,
3071                                        struct spoolss_Notify *data,
3072                                        print_queue_struct *queue,
3073                                        struct spoolss_PrinterInfo2 *pinfo2,
3074                                        TALLOC_CTX *mem_ctx)
3075 {
3076         /* always respond 8 pages per minutes */
3077         /* a little hard ! */
3078         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with username
3083  ********************************************************************/
3084
3085 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3086                                     int snum,
3087                                     struct spoolss_Notify *data,
3088                                     print_queue_struct *queue,
3089                                     struct spoolss_PrinterInfo2 *pinfo2,
3090                                     TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with job status
3097  ********************************************************************/
3098
3099 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3100                                       int snum,
3101                                       struct spoolss_Notify *data,
3102                                       print_queue_struct *queue,
3103                                       struct spoolss_PrinterInfo2 *pinfo2,
3104                                       TALLOC_CTX *mem_ctx)
3105 {
3106         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with job name
3111  ********************************************************************/
3112
3113 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3114                                     int snum,
3115                                     struct spoolss_Notify *data,
3116                                     print_queue_struct *queue,
3117                                     struct spoolss_PrinterInfo2 *pinfo2,
3118                                     TALLOC_CTX *mem_ctx)
3119 {
3120         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3121 }
3122
3123 /*******************************************************************
3124  * fill a notify_info_data with job status
3125  ********************************************************************/
3126
3127 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3128                                              int snum,
3129                                              struct spoolss_Notify *data,
3130                                              print_queue_struct *queue,
3131                                              struct spoolss_PrinterInfo2 *pinfo2,
3132                                              TALLOC_CTX *mem_ctx)
3133 {
3134         /*
3135          * Now we're returning job status codes we just return a "" here. JRA.
3136          */
3137
3138         const char *p = "";
3139
3140 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3141         p = "unknown";
3142
3143         switch (queue->status) {
3144         case LPQ_QUEUED:
3145                 p = "Queued";
3146                 break;
3147         case LPQ_PAUSED:
3148                 p = "";    /* NT provides the paused string */
3149                 break;
3150         case LPQ_SPOOLING:
3151                 p = "Spooling";
3152                 break;
3153         case LPQ_PRINTING:
3154                 p = "Printing";
3155                 break;
3156         }
3157 #endif /* NO LONGER NEEDED. */
3158
3159         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with job time
3164  ********************************************************************/
3165
3166 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3167                                     int snum,
3168                                     struct spoolss_Notify *data,
3169                                     print_queue_struct *queue,
3170                                     struct spoolss_PrinterInfo2 *pinfo2,
3171                                     TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with job size
3178  ********************************************************************/
3179
3180 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3181                                     int snum,
3182                                     struct spoolss_Notify *data,
3183                                     print_queue_struct *queue,
3184                                     struct spoolss_PrinterInfo2 *pinfo2,
3185                                     TALLOC_CTX *mem_ctx)
3186 {
3187         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with page info
3192  ********************************************************************/
3193 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3194                                        int snum,
3195                                 struct spoolss_Notify *data,
3196                                 print_queue_struct *queue,
3197                                 struct spoolss_PrinterInfo2 *pinfo2,
3198                                 TALLOC_CTX *mem_ctx)
3199 {
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3201 }
3202
3203 /*******************************************************************
3204  * fill a notify_info_data with pages printed info.
3205  ********************************************************************/
3206 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3207                                          int snum,
3208                                 struct spoolss_Notify *data,
3209                                 print_queue_struct *queue,
3210                                 struct spoolss_PrinterInfo2 *pinfo2,
3211                                 TALLOC_CTX *mem_ctx)
3212 {
3213         /* Add code when back-end tracks this */
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3215 }
3216
3217 /*******************************************************************
3218  Fill a notify_info_data with job position.
3219  ********************************************************************/
3220
3221 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3222                                         int snum,
3223                                         struct spoolss_Notify *data,
3224                                         print_queue_struct *queue,
3225                                         struct spoolss_PrinterInfo2 *pinfo2,
3226                                         TALLOC_CTX *mem_ctx)
3227 {
3228         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3229 }
3230
3231 /*******************************************************************
3232  Fill a notify_info_data with submitted time.
3233  ********************************************************************/
3234
3235 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3236                                           int snum,
3237                                           struct spoolss_Notify *data,
3238                                           print_queue_struct *queue,
3239                                           struct spoolss_PrinterInfo2 *pinfo2,
3240                                           TALLOC_CTX *mem_ctx)
3241 {
3242         data->data.string.string = NULL;
3243         data->data.string.size = 0;
3244
3245         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3246                                &data->data.string.string,
3247                                &data->data.string.size);
3248
3249 }
3250
3251 struct s_notify_info_data_table
3252 {
3253         enum spoolss_NotifyType type;
3254         uint16_t field;
3255         const char *name;
3256         enum spoolss_NotifyTable variable_type;
3257         void (*fn) (struct messaging_context *msg_ctx,
3258                     int snum, struct spoolss_Notify *data,
3259                     print_queue_struct *queue,
3260                     struct spoolss_PrinterInfo2 *pinfo2,
3261                     TALLOC_CTX *mem_ctx);
3262 };
3263
3264 /* A table describing the various print notification constants and
3265    whether the notification data is a pointer to a variable sized
3266    buffer, a one value uint32_t or a two value uint32_t. */
3267
3268 static const struct s_notify_info_data_table notify_info_data_table[] =
3269 {
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3319 };
3320
3321 /*******************************************************************
3322  Return the variable_type of info_data structure.
3323 ********************************************************************/
3324
3325 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3326                                                                   uint16_t field)
3327 {
3328         int i=0;
3329
3330         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3331                 if ( (notify_info_data_table[i].type == type) &&
3332                      (notify_info_data_table[i].field == field) ) {
3333                         return notify_info_data_table[i].variable_type;
3334                 }
3335         }
3336
3337         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3338
3339         return (enum spoolss_NotifyTable) 0;
3340 }
3341
3342 /****************************************************************************
3343 ****************************************************************************/
3344
3345 static bool search_notify(enum spoolss_NotifyType type,
3346                           uint16_t field,
3347                           int *value)
3348 {
3349         int i;
3350
3351         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3352                 if (notify_info_data_table[i].type == type &&
3353                     notify_info_data_table[i].field == field &&
3354                     notify_info_data_table[i].fn != NULL) {
3355                         *value = i;
3356                         return true;
3357                 }
3358         }
3359
3360         return false;
3361 }
3362
3363 /****************************************************************************
3364 ****************************************************************************/
3365
3366 static void construct_info_data(struct spoolss_Notify *info_data,
3367                                 enum spoolss_NotifyType type,
3368                                 uint16_t field, int id)
3369 {
3370         info_data->type                 = type;
3371         info_data->field.field          = field;
3372         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3373         info_data->job_id               = id;
3374 }
3375
3376 /*******************************************************************
3377  *
3378  * fill a notify_info struct with info asked
3379  *
3380  ********************************************************************/
3381
3382 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3383                                           struct printer_handle *print_hnd,
3384                                           struct spoolss_NotifyInfo *info,
3385                                           struct spoolss_PrinterInfo2 *pinfo2,
3386                                           int snum,
3387                                           const struct spoolss_NotifyOptionType *option_type,
3388                                           uint32_t id,
3389                                           TALLOC_CTX *mem_ctx)
3390 {
3391         int field_num,j;
3392         enum spoolss_NotifyType type;
3393         uint16_t field;
3394
3395         struct spoolss_Notify *current_data;
3396         print_queue_struct *queue=NULL;
3397
3398         type = option_type->type;
3399
3400         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3401                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3402                 option_type->count, lp_servicename(snum)));
3403
3404         for(field_num=0; field_num < option_type->count; field_num++) {
3405                 field = option_type->fields[field_num].field;
3406
3407                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3408
3409                 if (!search_notify(type, field, &j) )
3410                         continue;
3411
3412                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3413                                                       struct spoolss_Notify,
3414                                                       info->count + 1);
3415                 if (info->notifies == NULL) {
3416                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3417                         return false;
3418                 }
3419
3420                 current_data = &info->notifies[info->count];
3421
3422                 construct_info_data(current_data, type, field, id);
3423
3424                 DEBUG(10, ("construct_notify_printer_info: "
3425                            "calling [%s]  snum=%d  printername=[%s])\n",
3426                            notify_info_data_table[j].name, snum,
3427                            pinfo2->printername));
3428
3429                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3430                                              queue, pinfo2, mem_ctx);
3431
3432                 info->count++;
3433         }
3434
3435         return true;
3436 }
3437
3438 /*******************************************************************
3439  *
3440  * fill a notify_info struct with info asked
3441  *
3442  ********************************************************************/
3443
3444 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3445                                        print_queue_struct *queue,
3446                                        struct spoolss_NotifyInfo *info,
3447                                        struct spoolss_PrinterInfo2 *pinfo2,
3448                                        int snum,
3449                                        const struct spoolss_NotifyOptionType *option_type,
3450                                        uint32_t id,
3451                                        TALLOC_CTX *mem_ctx)
3452 {
3453         int field_num,j;
3454         enum spoolss_NotifyType type;
3455         uint16_t field;
3456         struct spoolss_Notify *current_data;
3457
3458         DEBUG(4,("construct_notify_jobs_info\n"));
3459
3460         type = option_type->type;
3461
3462         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3463                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3464                 option_type->count));
3465
3466         for(field_num=0; field_num<option_type->count; field_num++) {
3467                 field = option_type->fields[field_num].field;
3468
3469                 if (!search_notify(type, field, &j) )
3470                         continue;
3471
3472                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3473                                                       struct spoolss_Notify,
3474                                                       info->count + 1);
3475                 if (info->notifies == NULL) {
3476                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3477                         return false;
3478                 }
3479
3480                 current_data=&(info->notifies[info->count]);
3481
3482                 construct_info_data(current_data, type, field, id);
3483                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3484                                              queue, pinfo2, mem_ctx);
3485                 info->count++;
3486         }
3487
3488         return true;
3489 }
3490
3491 /*
3492  * JFM: The enumeration is not that simple, it's even non obvious.
3493  *
3494  * let's take an example: I want to monitor the PRINTER SERVER for
3495  * the printer's name and the number of jobs currently queued.
3496  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3497  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3498  *
3499  * I have 3 printers on the back of my server.
3500  *
3501  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3502  * structures.
3503  *   Number     Data                    Id
3504  *      1       printer 1 name          1
3505  *      2       printer 1 cjob          1
3506  *      3       printer 2 name          2
3507  *      4       printer 2 cjob          2
3508  *      5       printer 3 name          3
3509  *      6       printer 3 name          3
3510  *
3511  * that's the print server case, the printer case is even worse.
3512  */
3513
3514 /*******************************************************************
3515  *
3516  * enumerate all printers on the printserver
3517  * fill a notify_info struct with info asked
3518  *
3519  ********************************************************************/
3520
3521 static WERROR printserver_notify_info(struct pipes_struct *p,
3522                                       struct policy_handle *hnd,
3523                                       struct spoolss_NotifyInfo *info,
3524                                       TALLOC_CTX *mem_ctx)
3525 {
3526         int snum;
3527         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3528         int n_services=lp_numservices();
3529         int i;
3530         struct spoolss_NotifyOption *option;
3531         struct spoolss_NotifyOptionType option_type;
3532         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3533         WERROR result;
3534
3535         DEBUG(4,("printserver_notify_info\n"));
3536
3537         if (!Printer)
3538                 return WERR_BADFID;
3539
3540         option = Printer->notify.option;
3541
3542         info->version   = 2;
3543         info->notifies  = NULL;
3544         info->count     = 0;
3545
3546         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3547            sending a ffpcn() request first */
3548
3549         if ( !option )
3550                 return WERR_BADFID;
3551
3552         for (i=0; i<option->count; i++) {
3553                 option_type = option->types[i];
3554
3555                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3556                         continue;
3557
3558                 for (snum = 0; snum < n_services; snum++) {
3559                         if (!lp_browseable(snum) ||
3560                             !lp_snum_ok(snum) ||
3561                             !lp_print_ok(snum)) {
3562                                 continue; /* skip */
3563                         }
3564
3565                         /* Maybe we should use the SYSTEM session_info here... */
3566                         result = winreg_get_printer(mem_ctx,
3567                                                     get_session_info_system(),
3568                                                     p->msg_ctx,
3569                                                     lp_servicename(snum),
3570                                                     &pinfo2);
3571                         if (!W_ERROR_IS_OK(result)) {
3572                                 DEBUG(4, ("printserver_notify_info: "
3573                                           "Failed to get printer [%s]\n",
3574                                           lp_servicename(snum)));
3575                                 continue;
3576                         }
3577
3578
3579                         construct_notify_printer_info(p->msg_ctx,
3580                                                       Printer, info,
3581                                                       pinfo2, snum,
3582                                                       &option_type, snum,
3583                                                       mem_ctx);
3584
3585                         TALLOC_FREE(pinfo2);
3586                 }
3587         }
3588
3589 #if 0
3590         /*
3591          * Debugging information, don't delete.
3592          */
3593
3594         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3595         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3596         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3597
3598         for (i=0; i<info->count; i++) {
3599                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3600                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3601                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3602         }
3603 #endif
3604
3605         return WERR_OK;
3606 }
3607
3608 /*******************************************************************
3609  *
3610  * fill a notify_info struct with info asked
3611  *
3612  ********************************************************************/
3613
3614 static WERROR printer_notify_info(struct pipes_struct *p,
3615                                   struct policy_handle *hnd,
3616                                   struct spoolss_NotifyInfo *info,
3617                                   TALLOC_CTX *mem_ctx)
3618 {
3619         int snum;
3620         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3621         int i;
3622         uint32_t id;
3623         struct spoolss_NotifyOption *option;
3624         struct spoolss_NotifyOptionType option_type;
3625         int count,j;
3626         print_queue_struct *queue=NULL;
3627         print_status_struct status;
3628         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3629         WERROR result;
3630
3631         DEBUG(4,("printer_notify_info\n"));
3632
3633         if (!Printer)
3634                 return WERR_BADFID;
3635
3636         option = Printer->notify.option;
3637         id = 0x0;
3638
3639         info->version   = 2;
3640         info->notifies  = NULL;
3641         info->count     = 0;
3642
3643         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3644            sending a ffpcn() request first */
3645
3646         if ( !option )
3647                 return WERR_BADFID;
3648
3649         get_printer_snum(p, hnd, &snum, NULL);
3650
3651         /* Maybe we should use the SYSTEM session_info here... */
3652         result = winreg_get_printer(mem_ctx,
3653                                     get_session_info_system(),
3654                                     p->msg_ctx,
3655                                     lp_servicename(snum), &pinfo2);
3656         if (!W_ERROR_IS_OK(result)) {
3657                 return WERR_BADFID;
3658         }
3659
3660         for (i=0; i<option->count; i++) {
3661                 option_type = option->types[i];
3662
3663                 switch (option_type.type) {
3664                 case PRINTER_NOTIFY_TYPE:
3665                         if (construct_notify_printer_info(p->msg_ctx,
3666                                                           Printer, info,
3667                                                           pinfo2, snum,
3668                                                           &option_type, id,
3669                                                           mem_ctx)) {
3670                                 id--;
3671                         }
3672                         break;
3673
3674                 case JOB_NOTIFY_TYPE:
3675
3676                         count = print_queue_status(p->msg_ctx, snum, &queue,
3677                                                    &status);
3678
3679                         for (j=0; j<count; j++) {
3680                                 construct_notify_jobs_info(p->msg_ctx,
3681                                                            &queue[j], info,
3682                                                            pinfo2, snum,
3683                                                            &option_type,
3684                                                            queue[j].job,
3685                                                            mem_ctx);
3686                         }
3687
3688                         SAFE_FREE(queue);
3689                         break;
3690                 }
3691         }
3692
3693         /*
3694          * Debugging information, don't delete.
3695          */
3696         /*
3697         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3698         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3699         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3700
3701         for (i=0; i<info->count; i++) {
3702                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3703                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3704                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3705         }
3706         */
3707
3708         talloc_free(pinfo2);
3709         return WERR_OK;
3710 }
3711
3712 /****************************************************************
3713  _spoolss_RouterRefreshPrinterChangeNotify
3714 ****************************************************************/
3715
3716 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3717                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3718 {
3719         struct spoolss_NotifyInfo *info;
3720
3721         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3722         WERROR result = WERR_BADFID;
3723
3724         /* we always have a spoolss_NotifyInfo struct */
3725         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3726         if (!info) {
3727                 result = WERR_NOMEM;
3728                 goto done;
3729         }
3730
3731         *r->out.info = info;
3732
3733         if (!Printer) {
3734                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3735                         "Invalid handle (%s:%u:%u).\n",
3736                         OUR_HANDLE(r->in.handle)));
3737                 goto done;
3738         }
3739
3740         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3741
3742         /*
3743          *      We are now using the change value, and
3744          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3745          *      I don't have a global notification system, I'm sending back all the
3746          *      information even when _NOTHING_ has changed.
3747          */
3748
3749         /* We need to keep track of the change value to send back in
3750            RRPCN replies otherwise our updates are ignored. */
3751
3752         Printer->notify.fnpcn = true;
3753
3754         if (Printer->notify.cli_chan != NULL &&
3755             Printer->notify.cli_chan->active_connections > 0) {
3756                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3757                         "Saving change value in request [%x]\n",
3758                         r->in.change_low));
3759                 Printer->notify.change = r->in.change_low;
3760         }
3761
3762         /* just ignore the spoolss_NotifyOption */
3763
3764         switch (Printer->printer_type) {
3765                 case SPLHND_SERVER:
3766                         result = printserver_notify_info(p, r->in.handle,
3767                                                          info, p->mem_ctx);
3768                         break;
3769
3770                 case SPLHND_PRINTER:
3771                         result = printer_notify_info(p, r->in.handle,
3772                                                      info, p->mem_ctx);
3773                         break;
3774         }
3775
3776         Printer->notify.fnpcn = false;
3777
3778 done:
3779         return result;
3780 }
3781
3782 /********************************************************************
3783  ********************************************************************/
3784
3785 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3786                                  const char *servername,
3787                                  const char *printername,
3788                                  const char **printername_p)
3789 {
3790         /* FIXME: add lp_force_printername() */
3791
3792         if (servername == NULL) {
3793                 *printername_p = talloc_strdup(mem_ctx, printername);
3794                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3795                 return WERR_OK;
3796         }
3797
3798         if (servername[0] == '\\' && servername[1] == '\\') {
3799                 servername += 2;
3800         }
3801
3802         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3803         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3804
3805         return WERR_OK;
3806 }
3807
3808 /********************************************************************
3809  ********************************************************************/
3810
3811 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3812                                           const char *printername)
3813 {
3814         if (dm == NULL) {
3815                 return;
3816         }
3817
3818         dm->devicename = talloc_strndup(dm, printername,
3819                                         MIN(strlen(printername), 31));
3820 }
3821
3822 /********************************************************************
3823  * construct_printer_info_0
3824  * fill a printer_info_0 struct
3825  ********************************************************************/
3826
3827 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3828                                       const struct auth_serversupplied_info *session_info,
3829                                       struct messaging_context *msg_ctx,
3830                                       struct spoolss_PrinterInfo2 *info2,
3831                                       const char *servername,
3832                                       struct spoolss_PrinterInfo0 *r,
3833                                       int snum)
3834 {
3835         int count;
3836         struct printer_session_counter *session_counter;
3837         struct timeval setuptime;
3838         print_status_struct status;
3839         WERROR result;
3840
3841         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3842         if (!W_ERROR_IS_OK(result)) {
3843                 return result;
3844         }
3845
3846         if (servername) {
3847                 r->servername = talloc_strdup(mem_ctx, servername);
3848                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3849         } else {
3850                 r->servername = NULL;
3851         }
3852
3853         count = print_queue_length(msg_ctx, snum, &status);
3854
3855         /* check if we already have a counter for this printer */
3856         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3857                 if (session_counter->snum == snum)
3858                         break;
3859         }
3860
3861         /* it's the first time, add it to the list */
3862         if (session_counter == NULL) {
3863                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3864                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3865                 session_counter->snum           = snum;
3866                 session_counter->counter        = 0;
3867                 DLIST_ADD(counter_list, session_counter);
3868         }
3869
3870         /* increment it */
3871         session_counter->counter++;
3872
3873         r->cjobs                        = count;
3874         r->total_jobs                   = 0;
3875         r->total_bytes                  = 0;
3876
3877         get_startup_time(&setuptime);
3878         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3879
3880         /* JFM:
3881          * the global_counter should be stored in a TDB as it's common to all the clients
3882          * and should be zeroed on samba startup
3883          */
3884         r->global_counter               = session_counter->counter;
3885         r->total_pages                  = 0;
3886         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3887         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3888         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3889         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3890         r->spooling                     = 0;
3891         r->max_spooling                 = 0;
3892         r->session_counter              = session_counter->counter;
3893         r->num_error_out_of_paper       = 0x0;
3894         r->num_error_not_ready          = 0x0;          /* number of print failure */
3895         r->job_error                    = 0x0;
3896         r->number_of_processors         = 0x1;
3897         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3898         r->high_part_total_bytes        = 0x0;
3899
3900         /* ChangeID in milliseconds*/
3901         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3902                                     info2->sharename, &r->change_id);
3903
3904         r->last_error                   = WERR_OK;
3905         r->status                       = nt_printq_status(status.status);
3906         r->enumerate_network_printers   = 0x0;
3907         r->c_setprinter                 = 0x0;
3908         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3909         r->processor_level              = 0x6;          /* 6  ???*/
3910         r->ref_ic                       = 0;
3911         r->reserved2                    = 0;
3912         r->reserved3                    = 0;
3913
3914         return WERR_OK;
3915 }
3916
3917
3918 /********************************************************************
3919  * construct_printer_info1
3920  * fill a spoolss_PrinterInfo1 struct
3921 ********************************************************************/
3922
3923 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3924                                       const struct spoolss_PrinterInfo2 *info2,
3925                                       uint32_t flags,
3926                                       const char *servername,
3927                                       struct spoolss_PrinterInfo1 *r,
3928                                       int snum)
3929 {
3930         WERROR result;
3931
3932         r->flags                = flags;
3933
3934         if (info2->comment == NULL || info2->comment[0] == '\0') {
3935                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3936         } else {
3937                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3938         }
3939         W_ERROR_HAVE_NO_MEMORY(r->comment);
3940
3941         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3942         if (!W_ERROR_IS_OK(result)) {
3943                 return result;
3944         }
3945
3946         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3947                                                   r->name,
3948                                                   info2->drivername,
3949                                                   r->comment);
3950         W_ERROR_HAVE_NO_MEMORY(r->description);
3951
3952         return WERR_OK;
3953 }
3954
3955 /********************************************************************
3956  * construct_printer_info2
3957  * fill a spoolss_PrinterInfo2 struct
3958 ********************************************************************/
3959
3960 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3961                                       struct messaging_context *msg_ctx,
3962                                       const struct spoolss_PrinterInfo2 *info2,
3963                                       const char *servername,
3964                                       struct spoolss_PrinterInfo2 *r,
3965                                       int snum)
3966 {
3967         int count;
3968         print_status_struct status;
3969         WERROR result;
3970
3971         count = print_queue_length(msg_ctx, snum, &status);
3972
3973         if (servername) {
3974                 r->servername           = talloc_strdup(mem_ctx, servername);
3975                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3976         } else {
3977                 r->servername           = NULL;
3978         }
3979
3980         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3981         if (!W_ERROR_IS_OK(result)) {
3982                 return result;
3983         }
3984
3985         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3986         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3987         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3988         W_ERROR_HAVE_NO_MEMORY(r->portname);
3989         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3990         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3991
3992         if (info2->comment[0] == '\0') {
3993                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3994         } else {
3995                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3996         }
3997         W_ERROR_HAVE_NO_MEMORY(r->comment);
3998
3999         r->location             = talloc_strdup(mem_ctx, info2->location);
4000         W_ERROR_HAVE_NO_MEMORY(r->location);
4001         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4002         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4003         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4004         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4005         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4006         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4007         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4008         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4009
4010         r->attributes           = info2->attributes;
4011
4012         r->priority             = info2->priority;
4013         r->defaultpriority      = info2->defaultpriority;
4014         r->starttime            = info2->starttime;
4015         r->untiltime            = info2->untiltime;
4016         r->status               = nt_printq_status(status.status);
4017         r->cjobs                = count;
4018         r->averageppm           = info2->averageppm;
4019
4020         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4021         if (!r->devmode) {
4022                 DEBUG(8,("Returning NULL Devicemode!\n"));
4023         }
4024
4025         compose_devicemode_devicename(r->devmode, r->printername);
4026
4027         r->secdesc = NULL;
4028
4029         if (info2->secdesc != NULL) {
4030                 /* don't use talloc_steal() here unless you do a deep steal of all
4031                    the SEC_DESC members */
4032
4033                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4034         }
4035
4036         return WERR_OK;
4037 }
4038
4039 /********************************************************************
4040  * construct_printer_info3
4041  * fill a spoolss_PrinterInfo3 struct
4042  ********************************************************************/
4043
4044 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4045                                       const struct spoolss_PrinterInfo2 *info2,
4046                                       const char *servername,
4047                                       struct spoolss_PrinterInfo3 *r,
4048                                       int snum)
4049 {
4050         /* These are the components of the SD we are returning. */
4051
4052         if (info2->secdesc != NULL) {
4053                 /* don't use talloc_steal() here unless you do a deep steal of all
4054                    the SEC_DESC members */
4055
4056                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4057                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4058         }
4059
4060         return WERR_OK;
4061 }
4062
4063 /********************************************************************
4064  * construct_printer_info4
4065  * fill a spoolss_PrinterInfo4 struct
4066  ********************************************************************/
4067
4068 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4069                                       const struct spoolss_PrinterInfo2 *info2,
4070                                       const char *servername,
4071                                       struct spoolss_PrinterInfo4 *r,
4072                                       int snum)
4073 {
4074         WERROR result;
4075
4076         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4077         if (!W_ERROR_IS_OK(result)) {
4078                 return result;
4079         }
4080
4081         if (servername) {
4082                 r->servername   = talloc_strdup(mem_ctx, servername);
4083                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4084         } else {
4085                 r->servername = NULL;
4086         }
4087
4088         r->attributes   = info2->attributes;
4089
4090         return WERR_OK;
4091 }
4092
4093 /********************************************************************
4094  * construct_printer_info5
4095  * fill a spoolss_PrinterInfo5 struct
4096  ********************************************************************/
4097
4098 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4099                                       const struct spoolss_PrinterInfo2 *info2,
4100                                       const char *servername,
4101                                       struct spoolss_PrinterInfo5 *r,
4102                                       int snum)
4103 {
4104         WERROR result;
4105
4106         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4107         if (!W_ERROR_IS_OK(result)) {
4108                 return result;
4109         }
4110
4111         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4112         W_ERROR_HAVE_NO_MEMORY(r->portname);
4113
4114         r->attributes   = info2->attributes;
4115
4116         /* these two are not used by NT+ according to MSDN */
4117         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4118         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4119
4120         return WERR_OK;
4121 }
4122
4123 /********************************************************************
4124  * construct_printer_info_6
4125  * fill a spoolss_PrinterInfo6 struct
4126  ********************************************************************/
4127
4128 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4129                                       struct messaging_context *msg_ctx,
4130                                       const struct spoolss_PrinterInfo2 *info2,
4131                                       const char *servername,
4132                                       struct spoolss_PrinterInfo6 *r,
4133                                       int snum)
4134 {
4135         int count;
4136         print_status_struct status;
4137
4138         count = print_queue_length(msg_ctx, snum, &status);
4139
4140         r->status = nt_printq_status(status.status);
4141
4142         return WERR_OK;
4143 }
4144
4145 /********************************************************************
4146  * construct_printer_info7
4147  * fill a spoolss_PrinterInfo7 struct
4148  ********************************************************************/
4149
4150 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4151                                       struct messaging_context *msg_ctx,
4152                                       const char *servername,
4153                                       struct spoolss_PrinterInfo7 *r,
4154                                       int snum)
4155 {
4156         struct auth_serversupplied_info *session_info;
4157         struct GUID guid;
4158         NTSTATUS status;
4159
4160         status = make_session_info_system(mem_ctx, &session_info);
4161         if (!NT_STATUS_IS_OK(status)) {
4162                 DEBUG(0, ("construct_printer_info7: "
4163                           "Could not create system session_info\n"));
4164                 return WERR_NOMEM;
4165         }
4166
4167         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4168                                  servername,
4169                                  lp_servicename(snum), &guid, NULL)) {
4170                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4171                 r->action = DSPRINT_PUBLISH;
4172         } else {
4173                 r->guid = talloc_strdup(mem_ctx, "");
4174                 r->action = DSPRINT_UNPUBLISH;
4175         }
4176         W_ERROR_HAVE_NO_MEMORY(r->guid);
4177
4178         TALLOC_FREE(session_info);
4179         return WERR_OK;
4180 }
4181
4182 /********************************************************************
4183  * construct_printer_info8
4184  * fill a spoolss_PrinterInfo8 struct
4185  ********************************************************************/
4186
4187 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4188                                       const struct spoolss_PrinterInfo2 *info2,
4189                                       const char *servername,
4190                                       struct spoolss_DeviceModeInfo *r,
4191                                       int snum)
4192 {
4193         WERROR result;
4194         const char *printername;
4195
4196         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4197         if (!W_ERROR_IS_OK(result)) {
4198                 return result;
4199         }
4200
4201         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4202         if (!r->devmode) {
4203                 DEBUG(8,("Returning NULL Devicemode!\n"));
4204         }
4205
4206         compose_devicemode_devicename(r->devmode, printername);
4207
4208         return WERR_OK;
4209 }
4210
4211
4212 /********************************************************************
4213 ********************************************************************/
4214
4215 static bool snum_is_shared_printer(int snum)
4216 {
4217         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4218 }
4219
4220 /********************************************************************
4221  Spoolss_enumprinters.
4222 ********************************************************************/
4223
4224 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4225                                            const struct auth_serversupplied_info *session_info,
4226                                            struct messaging_context *msg_ctx,
4227                                            const char *servername,
4228                                            uint32_t level,
4229                                            uint32_t flags,
4230                                            union spoolss_PrinterInfo **info_p,
4231                                            uint32_t *count_p)
4232 {
4233         int snum;
4234         int n_services = lp_numservices();
4235         union spoolss_PrinterInfo *info = NULL;
4236         uint32_t count = 0;
4237         WERROR result = WERR_OK;
4238
4239         *count_p = 0;
4240         *info_p = NULL;
4241
4242         for (snum = 0; snum < n_services; snum++) {
4243
4244                 const char *printer;
4245                 struct spoolss_PrinterInfo2 *info2;
4246
4247                 if (!snum_is_shared_printer(snum)) {
4248                         continue;
4249                 }
4250
4251                 printer = lp_const_servicename(snum);
4252
4253                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4254                         printer, snum));
4255
4256                 result = winreg_create_printer(mem_ctx,
4257                                                session_info,
4258                                                msg_ctx,
4259                                                printer);
4260                 if (!W_ERROR_IS_OK(result)) {
4261                         goto out;
4262                 }
4263
4264                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4265                                             union spoolss_PrinterInfo,
4266                                             count + 1);
4267                 if (!info) {
4268                         result = WERR_NOMEM;
4269                         goto out;
4270                 }
4271
4272                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4273                                             printer, &info2);
4274                 if (!W_ERROR_IS_OK(result)) {
4275                         goto out;
4276                 }
4277
4278                 switch (level) {
4279                 case 0:
4280                         result = construct_printer_info0(info, session_info,
4281                                                          msg_ctx, info2,
4282                                                          servername,
4283                                                          &info[count].info0, snum);
4284                         break;
4285                 case 1:
4286                         result = construct_printer_info1(info, info2, flags,
4287                                                          servername,
4288                                                          &info[count].info1, snum);
4289                         break;
4290                 case 2:
4291                         result = construct_printer_info2(info, msg_ctx, info2,
4292                                                          servername,
4293                                                          &info[count].info2, snum);
4294                         break;
4295                 case 4:
4296                         result = construct_printer_info4(info, info2,
4297                                                          servername,
4298                                                          &info[count].info4, snum);
4299                         break;
4300                 case 5:
4301                         result = construct_printer_info5(info, info2,
4302                                                          servername,
4303                                                          &info[count].info5, snum);
4304                         break;
4305
4306                 default:
4307                         result = WERR_UNKNOWN_LEVEL;
4308                         goto out;
4309                 }
4310
4311                 if (!W_ERROR_IS_OK(result)) {
4312                         goto out;
4313                 }
4314
4315                 count++;
4316         }
4317
4318         *count_p = count;
4319         *info_p = info;
4320
4321  out:
4322         if (!W_ERROR_IS_OK(result)) {
4323                 TALLOC_FREE(info);
4324                 return result;
4325         }
4326
4327         *info_p = info;
4328
4329         return WERR_OK;
4330 }
4331
4332 /********************************************************************
4333  * handle enumeration of printers at level 0
4334  ********************************************************************/
4335
4336 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4337                                   const struct auth_serversupplied_info *session_info,
4338                                   struct messaging_context *msg_ctx,
4339                                   uint32_t flags,
4340                                   const char *servername,
4341                                   union spoolss_PrinterInfo **info,
4342                                   uint32_t *count)
4343 {
4344         DEBUG(4,("enum_all_printers_info_0\n"));
4345
4346         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4347                                             servername, 0, flags, info, count);
4348 }
4349
4350
4351 /********************************************************************
4352 ********************************************************************/
4353
4354 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4355                                        const struct auth_serversupplied_info *session_info,
4356                                        struct messaging_context *msg_ctx,
4357                                        const char *servername,
4358                                        uint32_t flags,
4359                                        union spoolss_PrinterInfo **info,
4360                                        uint32_t *count)
4361 {
4362         DEBUG(4,("enum_all_printers_info_1\n"));
4363
4364         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4365                                             servername, 1, flags, info, count);
4366 }
4367
4368 /********************************************************************
4369  enum_all_printers_info_1_local.
4370 *********************************************************************/
4371
4372 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4373                                              const struct auth_serversupplied_info *session_info,
4374                                              struct messaging_context *msg_ctx,
4375                                              const char *servername,
4376                                              union spoolss_PrinterInfo **info,
4377                                              uint32_t *count)
4378 {
4379         DEBUG(4,("enum_all_printers_info_1_local\n"));
4380
4381         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4382                                         servername, PRINTER_ENUM_ICON8, info, count);
4383 }
4384
4385 /********************************************************************
4386  enum_all_printers_info_1_name.
4387 *********************************************************************/
4388
4389 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4390                                             const struct auth_serversupplied_info *session_info,
4391                                             struct messaging_context *msg_ctx,
4392                                             const char *servername,
4393                                             union spoolss_PrinterInfo **info,
4394                                             uint32_t *count)
4395 {
4396         const char *s = servername;
4397
4398         DEBUG(4,("enum_all_printers_info_1_name\n"));
4399
4400         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4401                 s = servername + 2;
4402         }
4403
4404         if (!is_myname_or_ipaddr(s)) {
4405                 return WERR_INVALID_NAME;
4406         }
4407
4408         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4409                                         servername, PRINTER_ENUM_ICON8, info, count);
4410 }
4411
4412 /********************************************************************
4413  enum_all_printers_info_1_network.
4414 *********************************************************************/
4415
4416 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4417                                                const struct auth_serversupplied_info *session_info,
4418                                                struct messaging_context *msg_ctx,
4419                                                const char *servername,
4420                                                union spoolss_PrinterInfo **info,
4421                                                uint32_t *count)
4422 {
4423         const char *s = servername;
4424
4425         DEBUG(4,("enum_all_printers_info_1_network\n"));
4426
4427         /* If we respond to a enum_printers level 1 on our name with flags
4428            set to PRINTER_ENUM_REMOTE with a list of printers then these
4429            printers incorrectly appear in the APW browse list.
4430            Specifically the printers for the server appear at the workgroup
4431            level where all the other servers in the domain are
4432            listed. Windows responds to this call with a
4433            WERR_CAN_NOT_COMPLETE so we should do the same. */
4434
4435         if (servername[0] == '\\' && servername[1] == '\\') {
4436                  s = servername + 2;
4437         }
4438
4439         if (is_myname_or_ipaddr(s)) {
4440                  return WERR_CAN_NOT_COMPLETE;
4441         }
4442
4443         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4444                                         servername, PRINTER_ENUM_NAME, info, count);
4445 }
4446
4447 /********************************************************************
4448  * api_spoolss_enumprinters
4449  *
4450  * called from api_spoolss_enumprinters (see this to understand)
4451  ********************************************************************/
4452
4453 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4454                                        const struct auth_serversupplied_info *session_info,
4455                                        struct messaging_context *msg_ctx,
4456                                        const char *servername,
4457                                        union spoolss_PrinterInfo **info,
4458                                        uint32_t *count)
4459 {
4460         DEBUG(4,("enum_all_printers_info_2\n"));
4461
4462         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4463                                             servername, 2, 0, info, count);
4464 }
4465
4466 /********************************************************************
4467  * handle enumeration of printers at level 1
4468  ********************************************************************/
4469
4470 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4471                                   const struct auth_serversupplied_info *session_info,
4472                                   struct messaging_context *msg_ctx,
4473                                   uint32_t flags,
4474                                   const char *servername,
4475                                   union spoolss_PrinterInfo **info,
4476                                   uint32_t *count)
4477 {
4478         /* Not all the flags are equals */
4479
4480         if (flags & PRINTER_ENUM_LOCAL) {
4481                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4482                                                       msg_ctx, servername, info, count);
4483         }
4484
4485         if (flags & PRINTER_ENUM_NAME) {
4486                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4487                                                      msg_ctx, servername, info,
4488                                                      count);
4489         }
4490
4491         if (flags & PRINTER_ENUM_NETWORK) {
4492                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4493                                                         msg_ctx, servername, info,
4494                                                         count);
4495         }
4496
4497         return WERR_OK; /* NT4sp5 does that */
4498 }
4499
4500 /********************************************************************
4501  * handle enumeration of printers at level 2
4502  ********************************************************************/
4503
4504 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4505                                   const struct auth_serversupplied_info *session_info,
4506                                   struct messaging_context *msg_ctx,
4507                                   uint32_t flags,
4508                                   const char *servername,
4509                                   union spoolss_PrinterInfo **info,
4510                                   uint32_t *count)
4511 {
4512         if (flags & PRINTER_ENUM_LOCAL) {
4513
4514                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4515                                                 servername,
4516                                                 info, count);
4517         }
4518
4519         if (flags & PRINTER_ENUM_NAME) {
4520                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4521                         return WERR_INVALID_NAME;
4522                 }
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_REMOTE) {
4530                 return WERR_UNKNOWN_LEVEL;
4531         }
4532
4533         return WERR_OK;
4534 }
4535
4536 /********************************************************************
4537  * handle enumeration of printers at level 4
4538  ********************************************************************/
4539
4540 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4541                                   const struct auth_serversupplied_info *session_info,
4542                                   struct messaging_context *msg_ctx,
4543                                   uint32_t flags,
4544                                   const char *servername,
4545                                   union spoolss_PrinterInfo **info,
4546                                   uint32_t *count)
4547 {
4548         DEBUG(4,("enum_all_printers_info_4\n"));
4549
4550         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4551                                             servername, 4, flags, info, count);
4552 }
4553
4554
4555 /********************************************************************
4556  * handle enumeration of printers at level 5
4557  ********************************************************************/
4558
4559 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4560                                   const struct auth_serversupplied_info *session_info,
4561                                   struct messaging_context *msg_ctx,
4562                                   uint32_t flags,
4563                                   const char *servername,
4564                                   union spoolss_PrinterInfo **info,
4565                                   uint32_t *count)
4566 {
4567         DEBUG(4,("enum_all_printers_info_5\n"));
4568
4569         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4570                                             servername, 5, flags, info, count);
4571 }
4572
4573 /****************************************************************
4574  _spoolss_EnumPrinters
4575 ****************************************************************/
4576
4577 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4578                              struct spoolss_EnumPrinters *r)
4579 {
4580         const struct auth_serversupplied_info *session_info = get_session_info_system();
4581         WERROR result;
4582
4583         /* that's an [in out] buffer */
4584
4585         if (!r->in.buffer && (r->in.offered != 0)) {
4586                 return WERR_INVALID_PARAM;
4587         }
4588
4589         DEBUG(4,("_spoolss_EnumPrinters\n"));
4590
4591         *r->out.needed = 0;
4592         *r->out.count = 0;
4593         *r->out.info = NULL;
4594
4595         /*
4596          * Level 1:
4597          *          flags==PRINTER_ENUM_NAME
4598          *           if name=="" then enumerates all printers
4599          *           if name!="" then enumerate the printer
4600          *          flags==PRINTER_ENUM_REMOTE
4601          *          name is NULL, enumerate printers
4602          * Level 2: name!="" enumerates printers, name can't be NULL
4603          * Level 3: doesn't exist
4604          * Level 4: does a local registry lookup
4605          * Level 5: same as Level 2
4606          */
4607
4608         if (r->in.server && r->in.server[0] == '\0') {
4609                 r->in.server = NULL;
4610         }
4611
4612         switch (r->in.level) {
4613         case 0:
4614                 result = enumprinters_level0(p->mem_ctx, session_info,
4615                                              p->msg_ctx, r->in.flags,
4616                                              r->in.server,
4617                                              r->out.info, r->out.count);
4618                 break;
4619         case 1:
4620                 result = enumprinters_level1(p->mem_ctx, session_info,
4621                                              p->msg_ctx, r->in.flags,
4622                                              r->in.server,
4623                                              r->out.info, r->out.count);
4624                 break;
4625         case 2:
4626                 result = enumprinters_level2(p->mem_ctx, session_info,
4627                                              p->msg_ctx, r->in.flags,
4628                                              r->in.server,
4629                                              r->out.info, r->out.count);
4630                 break;
4631         case 4:
4632                 result = enumprinters_level4(p->mem_ctx, session_info,
4633                                              p->msg_ctx, r->in.flags,
4634                                              r->in.server,
4635                                              r->out.info, r->out.count);
4636                 break;
4637         case 5:
4638                 result = enumprinters_level5(p->mem_ctx, session_info,
4639                                              p->msg_ctx, r->in.flags,
4640                                              r->in.server,
4641                                              r->out.info, r->out.count);
4642                 break;
4643         default:
4644                 return WERR_UNKNOWN_LEVEL;
4645         }
4646
4647         if (!W_ERROR_IS_OK(result)) {
4648                 return result;
4649         }
4650
4651         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4652                                                      spoolss_EnumPrinters,
4653                                                      *r->out.info, r->in.level,
4654                                                      *r->out.count);
4655         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4656         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4657
4658         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4659 }
4660
4661 /****************************************************************
4662  _spoolss_GetPrinter
4663 ****************************************************************/
4664
4665 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4666                            struct spoolss_GetPrinter *r)
4667 {
4668         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4669         struct spoolss_PrinterInfo2 *info2 = NULL;
4670         WERROR result = WERR_OK;
4671         int snum;
4672
4673         /* that's an [in out] buffer */
4674
4675         if (!r->in.buffer && (r->in.offered != 0)) {
4676                 return WERR_INVALID_PARAM;
4677         }
4678
4679         *r->out.needed = 0;
4680
4681         if (Printer == NULL) {
4682                 return WERR_BADFID;
4683         }
4684
4685         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4686                 return WERR_BADFID;
4687         }
4688
4689         result = winreg_get_printer(p->mem_ctx,
4690                                     get_session_info_system(),
4691                                     p->msg_ctx,
4692                                     lp_const_servicename(snum),
4693                                     &info2);
4694         if (!W_ERROR_IS_OK(result)) {
4695                 goto out;
4696         }
4697
4698         switch (r->in.level) {
4699         case 0:
4700                 result = construct_printer_info0(p->mem_ctx,
4701                                                  get_session_info_system(),
4702                                                  p->msg_ctx,
4703                                                  info2,
4704                                                  Printer->servername,
4705                                                  &r->out.info->info0,
4706                                                  snum);
4707                 break;
4708         case 1:
4709                 result = construct_printer_info1(p->mem_ctx, info2,
4710                                                  PRINTER_ENUM_ICON8,
4711                                                  Printer->servername,
4712                                                  &r->out.info->info1, snum);
4713                 break;
4714         case 2:
4715                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4716                                                  Printer->servername,
4717                                                  &r->out.info->info2, snum);
4718                 break;
4719         case 3:
4720                 result = construct_printer_info3(p->mem_ctx, info2,
4721                                                  Printer->servername,
4722                                                  &r->out.info->info3, snum);
4723                 break;
4724         case 4:
4725                 result = construct_printer_info4(p->mem_ctx, info2,
4726                                                  Printer->servername,
4727                                                  &r->out.info->info4, snum);
4728                 break;
4729         case 5:
4730                 result = construct_printer_info5(p->mem_ctx, info2,
4731                                                  Printer->servername,
4732                                                  &r->out.info->info5, snum);
4733                 break;
4734         case 6:
4735                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4736                                                  Printer->servername,
4737                                                  &r->out.info->info6, snum);
4738                 break;
4739         case 7:
4740                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4741                                                  Printer->servername,
4742                                                  &r->out.info->info7, snum);
4743                 break;
4744         case 8:
4745                 result = construct_printer_info8(p->mem_ctx, info2,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info8, snum);
4748                 break;
4749         default:
4750                 result = WERR_UNKNOWN_LEVEL;
4751                 break;
4752         }
4753
4754  out:
4755         if (!W_ERROR_IS_OK(result)) {
4756                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4757                           r->in.level, win_errstr(result)));
4758                 TALLOC_FREE(r->out.info);
4759                 return result;
4760         }
4761
4762         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4763                                                r->out.info, r->in.level);
4764         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4765
4766         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4767 }
4768
4769 /********************************************************************
4770  ********************************************************************/
4771
4772 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4773         do { \
4774                 if (in && strlen(in)) { \
4775                         out = talloc_strdup(mem_ctx, in); \
4776                 } else { \
4777                         out = talloc_strdup(mem_ctx, ""); \
4778                 } \
4779                 W_ERROR_HAVE_NO_MEMORY(out); \
4780         } while (0);
4781
4782 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4783         do { \
4784                 if (in && strlen(in)) { \
4785                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4786                 } else { \
4787                         out = talloc_strdup(mem_ctx, ""); \
4788                 } \
4789                 W_ERROR_HAVE_NO_MEMORY(out); \
4790         } while (0);
4791
4792 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4793                                                   const char **string_array,
4794                                                   const char ***presult,
4795                                                   const char *cservername,
4796                                                   const char *arch,
4797                                                   int version)
4798 {
4799         int i, num_strings = 0;
4800         const char **array = NULL;
4801
4802         if (string_array == NULL) {
4803                 return WERR_INVALID_PARAMETER;
4804         }
4805
4806         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4807                 const char *str = NULL;
4808
4809                 if (cservername == NULL || arch == NULL) {
4810                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4811                 } else {
4812                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4813                 }
4814
4815                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4816                         TALLOC_FREE(array);
4817                         return WERR_NOMEM;
4818                 }
4819         }
4820
4821         if (i > 0) {
4822                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4823                              &array, &num_strings);
4824         }
4825
4826         if (presult) {
4827                 *presult = array;
4828         }
4829
4830         return WERR_OK;
4831 }
4832
4833 /********************************************************************
4834  * fill a spoolss_DriverInfo1 struct
4835  ********************************************************************/
4836
4837 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4838                                         struct spoolss_DriverInfo1 *r,
4839                                         const struct spoolss_DriverInfo8 *driver,
4840                                         const char *servername)
4841 {
4842         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4843         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4844
4845         return WERR_OK;
4846 }
4847
4848 /********************************************************************
4849  * fill a spoolss_DriverInfo2 struct
4850  ********************************************************************/
4851
4852 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4853                                         struct spoolss_DriverInfo2 *r,
4854                                         const struct spoolss_DriverInfo8 *driver,
4855                                         const char *servername)
4856
4857 {
4858         const char *cservername = canon_servername(servername);
4859
4860         r->version              = driver->version;
4861
4862         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4863         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4864         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4865         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4866
4867         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4868                                driver->architecture,
4869                                driver->version,
4870                                driver->driver_path,
4871                                r->driver_path);
4872
4873         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4874                                driver->architecture,
4875                                driver->version,
4876                                driver->data_file,
4877                                r->data_file);
4878
4879         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4880                                driver->architecture,
4881                                driver->version,
4882                                driver->config_file,
4883                                r->config_file);
4884
4885         return WERR_OK;
4886 }
4887
4888 /********************************************************************
4889  * fill a spoolss_DriverInfo3 struct
4890  ********************************************************************/
4891
4892 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4893                                         struct spoolss_DriverInfo3 *r,
4894                                         const struct spoolss_DriverInfo8 *driver,
4895                                         const char *servername)
4896 {
4897         const char *cservername = canon_servername(servername);
4898
4899         r->version              = driver->version;
4900
4901         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4902         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4903         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4904         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4905
4906         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4907                                driver->architecture,
4908                                driver->version,
4909                                driver->driver_path,
4910                                r->driver_path);
4911
4912         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4913                                driver->architecture,
4914                                driver->version,
4915                                driver->data_file,
4916                                r->data_file);
4917
4918         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4919                                driver->architecture,
4920                                driver->version,
4921                                driver->config_file,
4922                                r->config_file);
4923
4924         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4925                                driver->architecture,
4926                                driver->version,
4927                                driver->help_file,
4928                                r->help_file);
4929
4930         FILL_DRIVER_STRING(mem_ctx,
4931                            driver->monitor_name,
4932                            r->monitor_name);
4933
4934         FILL_DRIVER_STRING(mem_ctx,
4935                            driver->default_datatype,
4936                            r->default_datatype);
4937
4938         return string_array_from_driver_info(mem_ctx,
4939                                              driver->dependent_files,
4940                                              &r->dependent_files,
4941                                              cservername,
4942                                              driver->architecture,
4943                                              driver->version);
4944 }
4945
4946 /********************************************************************
4947  * fill a spoolss_DriverInfo4 struct
4948  ********************************************************************/
4949
4950 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4951                                         struct spoolss_DriverInfo4 *r,
4952                                         const struct spoolss_DriverInfo8 *driver,
4953                                         const char *servername)
4954 {
4955         const char *cservername = canon_servername(servername);
4956         WERROR result;
4957
4958         r->version              = driver->version;
4959
4960         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4961         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4962         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4963         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4964
4965         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4966                                driver->architecture,
4967                                driver->version,
4968                                driver->driver_path,
4969                                r->driver_path);
4970
4971         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4972                                driver->architecture,
4973                                driver->version,
4974                                driver->data_file,
4975                                r->data_file);
4976
4977         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4978                                driver->architecture,
4979                                driver->version,
4980                                driver->config_file,
4981                                r->config_file);
4982
4983         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4984                                driver->architecture,
4985                                driver->version,
4986                                driver->help_file,
4987                                r->help_file);
4988
4989         result = string_array_from_driver_info(mem_ctx,
4990                                                driver->dependent_files,
4991                                                &r->dependent_files,
4992                                                cservername,
4993                                                driver->architecture,
4994                                                driver->version);
4995         if (!W_ERROR_IS_OK(result)) {
4996                 return result;
4997         }
4998
4999         FILL_DRIVER_STRING(mem_ctx,
5000                            driver->monitor_name,
5001                            r->monitor_name);
5002
5003         FILL_DRIVER_STRING(mem_ctx,
5004                            driver->default_datatype,
5005                            r->default_datatype);
5006
5007
5008         result = string_array_from_driver_info(mem_ctx,
5009                                                driver->previous_names,
5010                                                &r->previous_names,
5011                                                NULL, NULL, 0);
5012
5013         return result;
5014 }
5015
5016 /********************************************************************
5017  * fill a spoolss_DriverInfo5 struct
5018  ********************************************************************/
5019
5020 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5021                                         struct spoolss_DriverInfo5 *r,
5022                                         const struct spoolss_DriverInfo8 *driver,
5023                                         const char *servername)
5024 {
5025         const char *cservername = canon_servername(servername);
5026
5027         r->version              = driver->version;
5028
5029         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5030         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5031         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5032         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5033
5034         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5035                                driver->architecture,
5036                                driver->version,
5037                                driver->driver_path,
5038                                r->driver_path);
5039
5040         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5041                                driver->architecture,
5042                                driver->version,
5043                                driver->data_file,
5044                                r->data_file);
5045
5046         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5047                                driver->architecture,
5048                                driver->version,
5049                                driver->config_file,
5050                                r->config_file);
5051
5052         r->driver_attributes    = 0;
5053         r->config_version       = 0;
5054         r->driver_version       = 0;
5055
5056         return WERR_OK;
5057 }
5058 /********************************************************************
5059  * fill a spoolss_DriverInfo6 struct
5060  ********************************************************************/
5061
5062 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5063                                         struct spoolss_DriverInfo6 *r,
5064                                         const struct spoolss_DriverInfo8 *driver,
5065                                         const char *servername)
5066 {
5067         const char *cservername = canon_servername(servername);
5068         WERROR result;
5069
5070         r->version              = driver->version;
5071
5072         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5073         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5074         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5075         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5076
5077         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5078                                driver->architecture,
5079                                driver->version,
5080                                driver->driver_path,
5081                                r->driver_path);
5082
5083         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5084                                driver->architecture,
5085                                driver->version,
5086                                driver->data_file,
5087                                r->data_file);
5088
5089         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5090                                driver->architecture,
5091                                driver->version,
5092                                driver->config_file,
5093                                r->config_file);
5094
5095         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5096                                driver->architecture,
5097                                driver->version,
5098                                driver->help_file,
5099                                r->help_file);
5100
5101         FILL_DRIVER_STRING(mem_ctx,
5102                            driver->monitor_name,
5103                            r->monitor_name);
5104
5105         FILL_DRIVER_STRING(mem_ctx,
5106                            driver->default_datatype,
5107                            r->default_datatype);
5108
5109         result = string_array_from_driver_info(mem_ctx,
5110                                                driver->dependent_files,
5111                                                &r->dependent_files,
5112                                                cservername,
5113                                                driver->architecture,
5114                                                driver->version);
5115         if (!W_ERROR_IS_OK(result)) {
5116                 return result;
5117         }
5118
5119         result = string_array_from_driver_info(mem_ctx,
5120                                                driver->previous_names,
5121                                                &r->previous_names,
5122                                                NULL, NULL, 0);
5123         if (!W_ERROR_IS_OK(result)) {
5124                 return result;
5125         }
5126
5127         r->driver_date          = driver->driver_date;
5128         r->driver_version       = driver->driver_version;
5129
5130         FILL_DRIVER_STRING(mem_ctx,
5131                            driver->manufacturer_name,
5132                            r->manufacturer_name);
5133         FILL_DRIVER_STRING(mem_ctx,
5134                            driver->manufacturer_url,
5135                            r->manufacturer_url);
5136         FILL_DRIVER_STRING(mem_ctx,
5137                            driver->hardware_id,
5138                            r->hardware_id);
5139         FILL_DRIVER_STRING(mem_ctx,
5140                            driver->provider,
5141                            r->provider);
5142
5143         return WERR_OK;
5144 }
5145
5146 /********************************************************************
5147  * fill a spoolss_DriverInfo8 struct
5148  ********************************************************************/
5149
5150 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5151                                         struct spoolss_DriverInfo8 *r,
5152                                         const struct spoolss_DriverInfo8 *driver,
5153                                         const char *servername)
5154 {
5155         const char *cservername = canon_servername(servername);
5156         WERROR result;
5157
5158         r->version              = driver->version;
5159
5160         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5161         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5162         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5163         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5164
5165         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5166                                driver->architecture,
5167                                driver->version,
5168                                driver->driver_path,
5169                                r->driver_path);
5170
5171         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5172                                driver->architecture,
5173                                driver->version,
5174                                driver->data_file,
5175                                r->data_file);
5176
5177         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5178                                driver->architecture,
5179                                driver->version,
5180                                driver->config_file,
5181                                r->config_file);
5182
5183         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5184                                driver->architecture,
5185                                driver->version,
5186                                driver->help_file,
5187                                r->help_file);
5188
5189         FILL_DRIVER_STRING(mem_ctx,
5190                            driver->monitor_name,
5191                            r->monitor_name);
5192
5193         FILL_DRIVER_STRING(mem_ctx,
5194                            driver->default_datatype,
5195                            r->default_datatype);
5196
5197         result = string_array_from_driver_info(mem_ctx,
5198                                                driver->dependent_files,
5199                                                &r->dependent_files,
5200                                                cservername,
5201                                                driver->architecture,
5202                                                driver->version);
5203         if (!W_ERROR_IS_OK(result)) {
5204                 return result;
5205         }
5206
5207         result = string_array_from_driver_info(mem_ctx,
5208                                                driver->previous_names,
5209                                                &r->previous_names,
5210                                                NULL, NULL, 0);
5211         if (!W_ERROR_IS_OK(result)) {
5212                 return result;
5213         }
5214
5215         r->driver_date          = driver->driver_date;
5216         r->driver_version       = driver->driver_version;
5217
5218         FILL_DRIVER_STRING(mem_ctx,
5219                            driver->manufacturer_name,
5220                            r->manufacturer_name);
5221         FILL_DRIVER_STRING(mem_ctx,
5222                            driver->manufacturer_url,
5223                            r->manufacturer_url);
5224         FILL_DRIVER_STRING(mem_ctx,
5225                            driver->hardware_id,
5226                            r->hardware_id);
5227         FILL_DRIVER_STRING(mem_ctx,
5228                            driver->provider,
5229                            r->provider);
5230
5231         FILL_DRIVER_STRING(mem_ctx,
5232                            driver->print_processor,
5233                            r->print_processor);
5234         FILL_DRIVER_STRING(mem_ctx,
5235                            driver->vendor_setup,
5236                            r->vendor_setup);
5237
5238         result = string_array_from_driver_info(mem_ctx,
5239                                                driver->color_profiles,
5240                                                &r->color_profiles,
5241                                                NULL, NULL, 0);
5242         if (!W_ERROR_IS_OK(result)) {
5243                 return result;
5244         }
5245
5246         FILL_DRIVER_STRING(mem_ctx,
5247                            driver->inf_path,
5248                            r->inf_path);
5249
5250         r->printer_driver_attributes    = driver->printer_driver_attributes;
5251
5252         result = string_array_from_driver_info(mem_ctx,
5253                                                driver->core_driver_dependencies,
5254                                                &r->core_driver_dependencies,
5255                                                NULL, NULL, 0);
5256         if (!W_ERROR_IS_OK(result)) {
5257                 return result;
5258         }
5259
5260         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5261         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5262
5263         return WERR_OK;
5264 }
5265
5266 #if 0 /* disabled until marshalling issues are resolved - gd */
5267 /********************************************************************
5268  ********************************************************************/
5269
5270 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5271                                           struct spoolss_DriverFileInfo *r,
5272                                           const char *cservername,
5273                                           const char *file_name,
5274                                           enum spoolss_DriverFileType file_type,
5275                                           uint32_t file_version)
5276 {
5277         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5278                                           cservername, file_name);
5279         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5280         r->file_type    = file_type;
5281         r->file_version = file_version;
5282
5283         return WERR_OK;
5284 }
5285
5286 /********************************************************************
5287  ********************************************************************/
5288
5289 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5290                                                  const struct spoolss_DriverInfo8 *driver,
5291                                                  const char *cservername,
5292                                                  struct spoolss_DriverFileInfo **info_p,
5293                                                  uint32_t *count_p)
5294 {
5295         struct spoolss_DriverFileInfo *info = NULL;
5296         uint32_t count = 0;
5297         WERROR result;
5298         uint32_t i;
5299
5300         *info_p = NULL;
5301         *count_p = 0;
5302
5303         if (strlen(driver->driver_path)) {
5304                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5305                                             struct spoolss_DriverFileInfo,
5306                                             count + 1);
5307                 W_ERROR_HAVE_NO_MEMORY(info);
5308                 result = fill_spoolss_DriverFileInfo(info,
5309                                                      &info[count],
5310                                                      cservername,
5311                                                      driver->driver_path,
5312                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5313                                                      0);
5314                 W_ERROR_NOT_OK_RETURN(result);
5315                 count++;
5316         }
5317
5318         if (strlen(driver->config_file)) {
5319                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5320                                             struct spoolss_DriverFileInfo,
5321                                             count + 1);
5322                 W_ERROR_HAVE_NO_MEMORY(info);
5323                 result = fill_spoolss_DriverFileInfo(info,
5324                                                      &info[count],
5325                                                      cservername,
5326                                                      driver->config_file,
5327                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5328                                                      0);
5329                 W_ERROR_NOT_OK_RETURN(result);
5330                 count++;
5331         }
5332
5333         if (strlen(driver->data_file)) {
5334                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5335                                             struct spoolss_DriverFileInfo,
5336                                             count + 1);
5337                 W_ERROR_HAVE_NO_MEMORY(info);
5338                 result = fill_spoolss_DriverFileInfo(info,
5339                                                      &info[count],
5340                                                      cservername,
5341                                                      driver->data_file,
5342                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5343                                                      0);
5344                 W_ERROR_NOT_OK_RETURN(result);
5345                 count++;
5346         }
5347
5348         if (strlen(driver->help_file)) {
5349                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5350                                             struct spoolss_DriverFileInfo,
5351                                             count + 1);
5352                 W_ERROR_HAVE_NO_MEMORY(info);
5353                 result = fill_spoolss_DriverFileInfo(info,
5354                                                      &info[count],
5355                                                      cservername,
5356                                                      driver->help_file,
5357                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5358                                                      0);
5359                 W_ERROR_NOT_OK_RETURN(result);
5360                 count++;
5361         }
5362
5363         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5364                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5365                                             struct spoolss_DriverFileInfo,
5366                                             count + 1);
5367                 W_ERROR_HAVE_NO_MEMORY(info);
5368                 result = fill_spoolss_DriverFileInfo(info,
5369                                                      &info[count],
5370                                                      cservername,
5371                                                      driver->dependent_files[i],
5372                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5373                                                      0);
5374                 W_ERROR_NOT_OK_RETURN(result);
5375                 count++;
5376         }
5377
5378         *info_p = info;
5379         *count_p = count;
5380
5381         return WERR_OK;
5382 }
5383
5384 /********************************************************************
5385  * fill a spoolss_DriverInfo101 struct
5386  ********************************************************************/
5387
5388 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5389                                           struct spoolss_DriverInfo101 *r,
5390                                           const struct spoolss_DriverInfo8 *driver,
5391                                           const char *servername)
5392 {
5393         const char *cservername = canon_servername(servername);
5394         WERROR result;
5395
5396         r->version              = driver->version;
5397
5398         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5399         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5400         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5401         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5402
5403         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5404                                                     cservername,
5405                                                     &r->file_info,
5406                                                     &r->file_count);
5407         if (!W_ERROR_IS_OK(result)) {
5408                 return result;
5409         }
5410
5411         FILL_DRIVER_STRING(mem_ctx,
5412                            driver->monitor_name,
5413                            r->monitor_name);
5414
5415         FILL_DRIVER_STRING(mem_ctx,
5416                            driver->default_datatype,
5417                            r->default_datatype);
5418
5419         result = string_array_from_driver_info(mem_ctx,
5420                                                driver->previous_names,
5421                                                &r->previous_names,
5422                                                NULL, NULL, 0);
5423         if (!W_ERROR_IS_OK(result)) {
5424                 return result;
5425         }
5426
5427         r->driver_date          = driver->driver_date;
5428         r->driver_version       = driver->driver_version;
5429
5430         FILL_DRIVER_STRING(mem_ctx,
5431                            driver->manufacturer_name,
5432                            r->manufacturer_name);
5433         FILL_DRIVER_STRING(mem_ctx,
5434                            driver->manufacturer_url,
5435                            r->manufacturer_url);
5436         FILL_DRIVER_STRING(mem_ctx,
5437                            driver->hardware_id,
5438                            r->hardware_id);
5439         FILL_DRIVER_STRING(mem_ctx,
5440                            driver->provider,
5441                            r->provider);
5442
5443         return WERR_OK;
5444 }
5445 #endif
5446 /********************************************************************
5447  ********************************************************************/
5448
5449 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5450                                                   const struct auth_serversupplied_info *session_info,
5451                                                   struct messaging_context *msg_ctx,
5452                                                   uint32_t level,
5453                                                   union spoolss_DriverInfo *r,
5454                                                   int snum,
5455                                                   const char *servername,
5456                                                   const char *architecture,
5457                                                   uint32_t version)
5458 {
5459         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5460         struct spoolss_DriverInfo8 *driver;
5461         WERROR result;
5462
5463         if (level == 101) {
5464                 return WERR_UNKNOWN_LEVEL;
5465         }
5466
5467         result = winreg_get_printer(mem_ctx,
5468                                     session_info,
5469                                     msg_ctx,
5470                                     lp_const_servicename(snum),
5471                                     &pinfo2);
5472
5473         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5474                 win_errstr(result)));
5475
5476         if (!W_ERROR_IS_OK(result)) {
5477                 return WERR_INVALID_PRINTER_NAME;
5478         }
5479
5480         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5481                                    architecture,
5482                                    pinfo2->drivername, version, &driver);
5483
5484         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5485                 win_errstr(result)));
5486
5487         if (!W_ERROR_IS_OK(result)) {
5488                 /*
5489                  * Is this a W2k client ?
5490                  */
5491
5492                 if (version < 3) {
5493                         talloc_free(pinfo2);
5494                         return WERR_UNKNOWN_PRINTER_DRIVER;
5495                 }
5496
5497                 /* Yes - try again with a WinNT driver. */
5498                 version = 2;
5499                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5500                                            architecture,
5501                                            pinfo2->drivername,
5502                                            version, &driver);
5503                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5504                         win_errstr(result)));
5505                 if (!W_ERROR_IS_OK(result)) {
5506                         talloc_free(pinfo2);
5507                         return WERR_UNKNOWN_PRINTER_DRIVER;
5508                 }
5509         }
5510
5511         switch (level) {
5512         case 1:
5513                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5514                 break;
5515         case 2:
5516                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5517                 break;
5518         case 3:
5519                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5520                 break;
5521         case 4:
5522                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5523                 break;
5524         case 5:
5525                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5526                 break;
5527         case 6:
5528                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5529                 break;
5530         case 8:
5531                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5532                 break;
5533 #if 0 /* disabled until marshalling issues are resolved - gd */
5534         case 101:
5535                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5536                 break;
5537 #endif
5538         default:
5539                 result = WERR_UNKNOWN_LEVEL;
5540                 break;
5541         }
5542
5543         talloc_free(pinfo2);
5544         talloc_free(driver);
5545
5546         return result;
5547 }
5548
5549 /****************************************************************
5550  _spoolss_GetPrinterDriver2
5551 ****************************************************************/
5552
5553 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5554                                   struct spoolss_GetPrinterDriver2 *r)
5555 {
5556         struct printer_handle *printer;
5557         WERROR result;
5558
5559         int snum;
5560
5561         /* that's an [in out] buffer */
5562
5563         if (!r->in.buffer && (r->in.offered != 0)) {
5564                 return WERR_INVALID_PARAM;
5565         }
5566
5567         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5568
5569         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5570                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5571                 return WERR_INVALID_PRINTER_NAME;
5572         }
5573
5574         *r->out.needed = 0;
5575         *r->out.server_major_version = 0;
5576         *r->out.server_minor_version = 0;
5577
5578         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5579                 return WERR_BADFID;
5580         }
5581
5582         result = construct_printer_driver_info_level(p->mem_ctx,
5583                                                      get_session_info_system(),
5584                                                      p->msg_ctx,
5585                                                      r->in.level, r->out.info,
5586                                                      snum, printer->servername,
5587                                                      r->in.architecture,
5588                                                      r->in.client_major_version);
5589         if (!W_ERROR_IS_OK(result)) {
5590                 TALLOC_FREE(r->out.info);
5591                 return result;
5592         }
5593
5594         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5595                                                r->out.info, r->in.level);
5596         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5597
5598         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5599 }
5600
5601
5602 /****************************************************************
5603  _spoolss_StartPagePrinter
5604 ****************************************************************/
5605
5606 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5607                                  struct spoolss_StartPagePrinter *r)
5608 {
5609         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5610
5611         if (!Printer) {
5612                 DEBUG(3,("_spoolss_StartPagePrinter: "
5613                         "Error in startpageprinter printer handle\n"));
5614                 return WERR_BADFID;
5615         }
5616
5617         Printer->page_started = true;
5618         return WERR_OK;
5619 }
5620
5621 /****************************************************************
5622  _spoolss_EndPagePrinter
5623 ****************************************************************/
5624
5625 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5626                                struct spoolss_EndPagePrinter *r)
5627 {
5628         int snum;
5629
5630         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5631
5632         if (!Printer) {
5633                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5634                         OUR_HANDLE(r->in.handle)));
5635                 return WERR_BADFID;
5636         }
5637
5638         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5639                 return WERR_BADFID;
5640
5641         Printer->page_started = false;
5642         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5643
5644         return WERR_OK;
5645 }
5646
5647 /****************************************************************
5648  _spoolss_StartDocPrinter
5649 ****************************************************************/
5650
5651 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5652                                 struct spoolss_StartDocPrinter *r)
5653 {
5654         struct spoolss_DocumentInfo1 *info_1;
5655         int snum;
5656         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5657         WERROR werr;
5658
5659         if (!Printer) {
5660                 DEBUG(2,("_spoolss_StartDocPrinter: "
5661                         "Invalid handle (%s:%u:%u)\n",
5662                         OUR_HANDLE(r->in.handle)));
5663                 return WERR_BADFID;
5664         }
5665
5666         if (Printer->jobid) {
5667                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5668                           "StartDocPrinter called twice! "
5669                           "(existing jobid = %d)\n", Printer->jobid));
5670                 return WERR_INVALID_HANDLE;
5671         }
5672
5673         if (r->in.level != 1) {
5674                 return WERR_UNKNOWN_LEVEL;
5675         }
5676
5677         info_1 = r->in.info.info1;
5678
5679         /*
5680          * a nice thing with NT is it doesn't listen to what you tell it.
5681          * when asked to send _only_ RAW datas, it tries to send datas
5682          * in EMF format.
5683          *
5684          * So I add checks like in NT Server ...
5685          */
5686
5687         if (info_1->datatype) {
5688                 if (strcmp(info_1->datatype, "RAW") != 0) {
5689                         *r->out.job_id = 0;
5690                         return WERR_INVALID_DATATYPE;
5691                 }
5692         }
5693
5694         /* get the share number of the printer */
5695         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5696                 return WERR_BADFID;
5697         }
5698
5699         werr = print_job_start(p->session_info,
5700                                p->msg_ctx,
5701                                p->client_id->name,
5702                                snum,
5703                                info_1->document_name,
5704                                info_1->output_file,
5705                                Printer->devmode,
5706                                &Printer->jobid);
5707
5708         /* An error occured in print_job_start() so return an appropriate
5709            NT error code. */
5710
5711         if (!W_ERROR_IS_OK(werr)) {
5712                 return werr;
5713         }
5714
5715         Printer->document_started = true;
5716         *r->out.job_id = Printer->jobid;
5717
5718         return WERR_OK;
5719 }
5720
5721 /****************************************************************
5722  _spoolss_EndDocPrinter
5723 ****************************************************************/
5724
5725 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5726                               struct spoolss_EndDocPrinter *r)
5727 {
5728         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5729         NTSTATUS status;
5730         int snum;
5731
5732         if (!Printer) {
5733                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5734                         OUR_HANDLE(r->in.handle)));
5735                 return WERR_BADFID;
5736         }
5737
5738         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5739                 return WERR_BADFID;
5740         }
5741
5742         Printer->document_started = false;
5743         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5744         if (!NT_STATUS_IS_OK(status)) {
5745                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5746                           "print_job_end failed [%s]\n",
5747                           nt_errstr(status)));
5748         }
5749
5750         Printer->jobid = 0;
5751         return ntstatus_to_werror(status);
5752 }
5753
5754 /****************************************************************
5755  _spoolss_WritePrinter
5756 ****************************************************************/
5757
5758 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5759                              struct spoolss_WritePrinter *r)
5760 {
5761         ssize_t buffer_written;
5762         int snum;
5763         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5764
5765         if (!Printer) {
5766                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5767                         OUR_HANDLE(r->in.handle)));
5768                 *r->out.num_written = r->in._data_size;
5769                 return WERR_BADFID;
5770         }
5771
5772         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5773                 return WERR_BADFID;
5774
5775         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5776         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5777                                                    snum, Printer->jobid,
5778                                                    (const char *)r->in.data.data,
5779                                                    (size_t)r->in._data_size);
5780         if (buffer_written == (ssize_t)-1) {
5781                 *r->out.num_written = 0;
5782                 if (errno == ENOSPC)
5783                         return WERR_NO_SPOOL_SPACE;
5784                 else
5785                         return WERR_ACCESS_DENIED;
5786         }
5787
5788         *r->out.num_written = r->in._data_size;
5789
5790         return WERR_OK;
5791 }
5792
5793 /********************************************************************
5794  * api_spoolss_getprinter
5795  * called from the spoolss dispatcher
5796  *
5797  ********************************************************************/
5798
5799 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5800                               struct pipes_struct *p)
5801 {
5802         const struct auth_serversupplied_info *session_info = p->session_info;
5803         int snum;
5804         WERROR errcode = WERR_BADFUNC;
5805         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5806
5807         if (!Printer) {
5808                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5809                         OUR_HANDLE(handle)));
5810                 return WERR_BADFID;
5811         }
5812
5813         if (!get_printer_snum(p, handle, &snum, NULL))
5814                 return WERR_BADFID;
5815
5816         switch (command) {
5817         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5818                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5819                 break;
5820         case SPOOLSS_PRINTER_CONTROL_RESUME:
5821         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5822                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5823                 break;
5824         case SPOOLSS_PRINTER_CONTROL_PURGE:
5825                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5826                 break;
5827         default:
5828                 return WERR_UNKNOWN_LEVEL;
5829         }
5830
5831         return errcode;
5832 }
5833
5834
5835 /****************************************************************
5836  _spoolss_AbortPrinter
5837  * From MSDN: "Deletes printer's spool file if printer is configured
5838  * for spooling"
5839 ****************************************************************/
5840
5841 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5842                              struct spoolss_AbortPrinter *r)
5843 {
5844         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5845         int             snum;
5846         WERROR          errcode = WERR_OK;
5847
5848         if (!Printer) {
5849                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5850                         OUR_HANDLE(r->in.handle)));
5851                 return WERR_BADFID;
5852         }
5853
5854         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5855                 return WERR_BADFID;
5856
5857         if (!Printer->document_started) {
5858                 return WERR_SPL_NO_STARTDOC;
5859         }
5860
5861         errcode = print_job_delete(p->session_info,
5862                                    p->msg_ctx,
5863                                    snum,
5864                                    Printer->jobid);
5865
5866         return errcode;
5867 }
5868
5869 /********************************************************************
5870  * called by spoolss_api_setprinter
5871  * when updating a printer description
5872  ********************************************************************/
5873
5874 static WERROR update_printer_sec(struct policy_handle *handle,
5875                                  struct pipes_struct *p,
5876                                  struct sec_desc_buf *secdesc_ctr)
5877 {
5878         struct spoolss_security_descriptor *new_secdesc = NULL;
5879         struct spoolss_security_descriptor *old_secdesc = NULL;
5880         const char *printer;
5881         WERROR result;
5882         int snum;
5883
5884         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5885
5886         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5887                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5888                          OUR_HANDLE(handle)));
5889
5890                 result = WERR_BADFID;
5891                 goto done;
5892         }
5893
5894         if (secdesc_ctr == NULL) {
5895                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5896                 result = WERR_INVALID_PARAM;
5897                 goto done;
5898         }
5899         printer = lp_const_servicename(snum);
5900
5901         /* Check the user has permissions to change the security
5902            descriptor.  By experimentation with two NT machines, the user
5903            requires Full Access to the printer to change security
5904            information. */
5905
5906         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5907                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5908                 result = WERR_ACCESS_DENIED;
5909                 goto done;
5910         }
5911
5912         /* NT seems to like setting the security descriptor even though
5913            nothing may have actually changed. */
5914         result = winreg_get_printer_secdesc(p->mem_ctx,
5915                                             get_session_info_system(),
5916                                             p->msg_ctx,
5917                                             printer,
5918                                             &old_secdesc);
5919         if (!W_ERROR_IS_OK(result)) {
5920                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5921                 result = WERR_BADFID;
5922                 goto done;
5923         }
5924
5925         if (DEBUGLEVEL >= 10) {
5926                 struct security_acl *the_acl;
5927                 int i;
5928
5929                 the_acl = old_secdesc->dacl;
5930                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5931                            printer, the_acl->num_aces));
5932
5933                 for (i = 0; i < the_acl->num_aces; i++) {
5934                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5935                                            &the_acl->aces[i].trustee),
5936                                   the_acl->aces[i].access_mask));
5937                 }
5938
5939                 the_acl = secdesc_ctr->sd->dacl;
5940
5941                 if (the_acl) {
5942                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5943                                    printer, the_acl->num_aces));
5944
5945                         for (i = 0; i < the_acl->num_aces; i++) {
5946                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5947                                                    &the_acl->aces[i].trustee),
5948                                            the_acl->aces[i].access_mask));
5949                         }
5950                 } else {
5951                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5952                 }
5953         }
5954
5955         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5956         if (new_secdesc == NULL) {
5957                 result = WERR_NOMEM;
5958                 goto done;
5959         }
5960
5961         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5962                 result = WERR_OK;
5963                 goto done;
5964         }
5965
5966         result = winreg_set_printer_secdesc(p->mem_ctx,
5967                                             get_session_info_system(),
5968                                             p->msg_ctx,
5969                                             printer,
5970                                             new_secdesc);
5971
5972  done:
5973         return result;
5974 }
5975
5976 /********************************************************************
5977  Canonicalize printer info from a client
5978  ********************************************************************/
5979
5980 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5981                              struct spoolss_SetPrinterInfo2 *info2,
5982                              int snum)
5983 {
5984         fstring printername;
5985         const char *p;
5986
5987         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5988                 "portname=%s drivername=%s comment=%s location=%s\n",
5989                 info2->servername, info2->printername, info2->sharename,
5990                 info2->portname, info2->drivername, info2->comment,
5991                 info2->location));
5992
5993         /* we force some elements to "correct" values */
5994         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5995         if (info2->servername == NULL) {
5996                 return false;
5997         }
5998         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5999         if (info2->sharename == NULL) {
6000                 return false;
6001         }
6002
6003         /* check to see if we allow printername != sharename */
6004         if (lp_force_printername(snum)) {
6005                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6006                                         global_myname(), info2->sharename);
6007         } else {
6008                 /* make sure printername is in \\server\printername format */
6009                 fstrcpy(printername, info2->printername);
6010                 p = printername;
6011                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6012                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6013                                 p++;
6014                 }
6015
6016                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6017                                         global_myname(), p);
6018         }
6019         if (info2->printername == NULL) {
6020                 return false;
6021         }
6022
6023         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6024         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6025
6026         return true;
6027 }
6028
6029 /****************************************************************************
6030 ****************************************************************************/
6031
6032 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6033 {
6034         char *cmd = lp_addport_cmd();
6035         char *command = NULL;
6036         int ret;
6037         bool is_print_op = false;
6038
6039         if ( !*cmd ) {
6040                 return WERR_ACCESS_DENIED;
6041         }
6042
6043         command = talloc_asprintf(ctx,
6044                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6045         if (!command) {
6046                 return WERR_NOMEM;
6047         }
6048
6049         if ( token )
6050                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6051
6052         DEBUG(10,("Running [%s]\n", command));
6053
6054         /********* BEGIN SePrintOperatorPrivilege **********/
6055
6056         if ( is_print_op )
6057                 become_root();
6058
6059         ret = smbrun(command, NULL);
6060
6061         if ( is_print_op )
6062                 unbecome_root();
6063
6064         /********* END SePrintOperatorPrivilege **********/
6065
6066         DEBUGADD(10,("returned [%d]\n", ret));
6067
6068         TALLOC_FREE(command);
6069
6070         if ( ret != 0 ) {
6071                 return WERR_ACCESS_DENIED;
6072         }
6073
6074         return WERR_OK;
6075 }
6076
6077 /****************************************************************************
6078 ****************************************************************************/
6079
6080 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6081                              struct spoolss_SetPrinterInfo2 *info2,
6082                              const char *remote_machine,
6083                              struct messaging_context *msg_ctx)
6084 {
6085         char *cmd = lp_addprinter_cmd();
6086         char **qlines;
6087         char *command = NULL;
6088         int numlines;
6089         int ret;
6090         int fd;
6091         bool is_print_op = false;
6092
6093         if (!remote_machine) {
6094                 return false;
6095         }
6096
6097         command = talloc_asprintf(ctx,
6098                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6099                         cmd, info2->printername, info2->sharename,
6100                         info2->portname, info2->drivername,
6101                         info2->location, info2->comment, remote_machine);
6102         if (!command) {
6103                 return false;
6104         }
6105
6106         if ( token )
6107                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6108
6109         DEBUG(10,("Running [%s]\n", command));
6110
6111         /********* BEGIN SePrintOperatorPrivilege **********/
6112
6113         if ( is_print_op )
6114                 become_root();
6115
6116         if ( (ret = smbrun(command, &fd)) == 0 ) {
6117                 /* Tell everyone we updated smb.conf. */
6118                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6119         }
6120
6121         if ( is_print_op )
6122                 unbecome_root();
6123
6124         /********* END SePrintOperatorPrivilege **********/
6125
6126         DEBUGADD(10,("returned [%d]\n", ret));
6127
6128         TALLOC_FREE(command);
6129
6130         if ( ret != 0 ) {
6131                 if (fd != -1)
6132                         close(fd);
6133                 return false;
6134         }
6135
6136         /* reload our services immediately */
6137         become_root();
6138         reload_services(msg_ctx, -1, false);
6139         unbecome_root();
6140
6141         numlines = 0;
6142         /* Get lines and convert them back to dos-codepage */
6143         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6144         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6145         close(fd);
6146
6147         /* Set the portname to what the script says the portname should be. */
6148         /* but don't require anything to be return from the script exit a good error code */
6149
6150         if (numlines) {
6151                 /* Set the portname to what the script says the portname should be. */
6152                 info2->portname = talloc_strdup(ctx, qlines[0]);
6153                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6154         }
6155
6156         TALLOC_FREE(qlines);
6157         return true;
6158 }
6159
6160 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6161                                const struct auth_serversupplied_info *session_info,
6162                                struct messaging_context *msg_ctx,
6163                                int snum,
6164                                struct spoolss_SetPrinterInfo2 *printer,
6165                                struct spoolss_PrinterInfo2 *old_printer)
6166 {
6167         bool force_update = (old_printer == NULL);
6168         const char *dnsdomname;
6169         const char *longname;
6170         const char *uncname;
6171         const char *spooling;
6172         DATA_BLOB buffer;
6173         WERROR result = WERR_OK;
6174
6175         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6176                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6177                 winreg_set_printer_dataex(mem_ctx,
6178                                           session_info,
6179                                           msg_ctx,
6180                                           printer->sharename,
6181                                           SPOOL_DSSPOOLER_KEY,
6182                                           SPOOL_REG_DRIVERNAME,
6183                                           REG_SZ,
6184                                           buffer.data,
6185                                           buffer.length);
6186
6187                 if (!force_update) {
6188                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6189                                 printer->drivername));
6190
6191                         notify_printer_driver(server_event_context(), msg_ctx,
6192                                               snum, printer->drivername ?
6193                                               printer->drivername : "");
6194                 }
6195         }
6196
6197         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6198                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6199                 winreg_set_printer_dataex(mem_ctx,
6200                                           session_info,
6201                                           msg_ctx,
6202                                           printer->sharename,
6203                                           SPOOL_DSSPOOLER_KEY,
6204                                           SPOOL_REG_DESCRIPTION,
6205                                           REG_SZ,
6206                                           buffer.data,
6207                                           buffer.length);
6208
6209                 if (!force_update) {
6210                         notify_printer_comment(server_event_context(), msg_ctx,
6211                                                snum, printer->comment ?
6212                                                printer->comment : "");
6213                 }
6214         }
6215
6216         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6217                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6218                 winreg_set_printer_dataex(mem_ctx,
6219                                           session_info,
6220                                           msg_ctx,
6221                                           printer->sharename,
6222                                           SPOOL_DSSPOOLER_KEY,
6223                                           SPOOL_REG_PRINTSHARENAME,
6224                                           REG_SZ,
6225                                           buffer.data,
6226                                           buffer.length);
6227
6228                 if (!force_update) {
6229                         notify_printer_sharename(server_event_context(),
6230                                                  msg_ctx,
6231                                                  snum, printer->sharename ?
6232                                                  printer->sharename : "");
6233                 }
6234         }
6235
6236         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6237                 const char *p;
6238
6239                 p = strrchr(printer->printername, '\\' );
6240                 if (p != NULL) {
6241                         p++;
6242                 } else {
6243                         p = printer->printername;
6244                 }
6245
6246                 push_reg_sz(mem_ctx, &buffer, p);
6247                 winreg_set_printer_dataex(mem_ctx,
6248                                           session_info,
6249                                           msg_ctx,
6250                                           printer->sharename,
6251                                           SPOOL_DSSPOOLER_KEY,
6252                                           SPOOL_REG_PRINTERNAME,
6253                                           REG_SZ,
6254                                           buffer.data,
6255                                           buffer.length);
6256
6257                 if (!force_update) {
6258                         notify_printer_printername(server_event_context(),
6259                                                    msg_ctx, snum, p ? p : "");
6260                 }
6261         }
6262
6263         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6264                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6265                 winreg_set_printer_dataex(mem_ctx,
6266                                           session_info,
6267                                           msg_ctx,
6268                                           printer->sharename,
6269                                           SPOOL_DSSPOOLER_KEY,
6270                                           SPOOL_REG_PORTNAME,
6271                                           REG_SZ,
6272                                           buffer.data,
6273                                           buffer.length);
6274
6275                 if (!force_update) {
6276                         notify_printer_port(server_event_context(),
6277                                             msg_ctx, snum, printer->portname ?
6278                                             printer->portname : "");
6279                 }
6280         }
6281
6282         if (force_update || !strequal(printer->location, old_printer->location)) {
6283                 push_reg_sz(mem_ctx, &buffer, printer->location);
6284                 winreg_set_printer_dataex(mem_ctx,
6285                                           session_info,
6286                                           msg_ctx,
6287                                           printer->sharename,
6288                                           SPOOL_DSSPOOLER_KEY,
6289                                           SPOOL_REG_LOCATION,
6290                                           REG_SZ,
6291                                           buffer.data,
6292                                           buffer.length);
6293
6294                 if (!force_update) {
6295                         notify_printer_location(server_event_context(),
6296                                                 msg_ctx, snum,
6297                                                 printer->location ?
6298                                                 printer->location : "");
6299                 }
6300         }
6301
6302         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6303                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6304                 winreg_set_printer_dataex(mem_ctx,
6305                                           session_info,
6306                                           msg_ctx,
6307                                           printer->sharename,
6308                                           SPOOL_DSSPOOLER_KEY,
6309                                           SPOOL_REG_PRINTSEPARATORFILE,
6310                                           REG_SZ,
6311                                           buffer.data,
6312                                           buffer.length);
6313
6314                 if (!force_update) {
6315                         notify_printer_sepfile(server_event_context(),
6316                                                msg_ctx, snum,
6317                                                printer->sepfile ?
6318                                                printer->sepfile : "");
6319                 }
6320         }
6321
6322         if (force_update || printer->starttime != old_printer->starttime) {
6323                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6324                 SIVAL(buffer.data, 0, printer->starttime);
6325                 winreg_set_printer_dataex(mem_ctx,
6326                                           session_info,
6327                                           msg_ctx,
6328                                           printer->sharename,
6329                                           SPOOL_DSSPOOLER_KEY,
6330                                           SPOOL_REG_PRINTSTARTTIME,
6331                                           REG_DWORD,
6332                                           buffer.data,
6333                                           buffer.length);
6334         }
6335
6336         if (force_update || printer->untiltime != old_printer->untiltime) {
6337                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6338                 SIVAL(buffer.data, 0, printer->untiltime);
6339                 winreg_set_printer_dataex(mem_ctx,
6340                                           session_info,
6341                                           msg_ctx,
6342                                           printer->sharename,
6343                                           SPOOL_DSSPOOLER_KEY,
6344                                           SPOOL_REG_PRINTENDTIME,
6345                                           REG_DWORD,
6346                                           buffer.data,
6347                                           buffer.length);
6348         }
6349
6350         if (force_update || printer->priority != old_printer->priority) {
6351                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6352                 SIVAL(buffer.data, 0, printer->priority);
6353                 winreg_set_printer_dataex(mem_ctx,
6354                                           session_info,
6355                                           msg_ctx,
6356                                           printer->sharename,
6357                                           SPOOL_DSSPOOLER_KEY,
6358                                           SPOOL_REG_PRIORITY,
6359                                           REG_DWORD,
6360                                           buffer.data,
6361                                           buffer.length);
6362         }
6363
6364         if (force_update || printer->attributes != old_printer->attributes) {
6365                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6366                 SIVAL(buffer.data, 0, (printer->attributes &
6367                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6368                 winreg_set_printer_dataex(mem_ctx,
6369                                           session_info,
6370                                           msg_ctx,
6371                                           printer->sharename,
6372                                           SPOOL_DSSPOOLER_KEY,
6373                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6374                                           REG_DWORD,
6375                                           buffer.data,
6376                                           buffer.length);
6377
6378                 switch (printer->attributes & 0x3) {
6379                         case 0:
6380                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6381                                 break;
6382                         case 1:
6383                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6384                                 break;
6385                         case 2:
6386                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6387                                 break;
6388                         default:
6389                                 spooling = "unknown";
6390                 }
6391                 push_reg_sz(mem_ctx, &buffer, spooling);
6392                 winreg_set_printer_dataex(mem_ctx,
6393                                           session_info,
6394                                           msg_ctx,
6395                                           printer->sharename,
6396                                           SPOOL_DSSPOOLER_KEY,
6397                                           SPOOL_REG_PRINTSPOOLING,
6398                                           REG_SZ,
6399                                           buffer.data,
6400                                           buffer.length);
6401         }
6402
6403         push_reg_sz(mem_ctx, &buffer, global_myname());
6404         winreg_set_printer_dataex(mem_ctx,
6405                                   session_info,
6406                                   msg_ctx,
6407                                   printer->sharename,
6408                                   SPOOL_DSSPOOLER_KEY,
6409                                   SPOOL_REG_SHORTSERVERNAME,
6410                                   REG_SZ,
6411                                   buffer.data,
6412                                   buffer.length);
6413
6414         dnsdomname = get_mydnsfullname();
6415         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6416                 longname = talloc_strdup(mem_ctx, dnsdomname);
6417         } else {
6418                 longname = talloc_strdup(mem_ctx, global_myname());
6419         }
6420         if (longname == NULL) {
6421                 result = WERR_NOMEM;
6422                 goto done;
6423         }
6424
6425         push_reg_sz(mem_ctx, &buffer, longname);
6426         winreg_set_printer_dataex(mem_ctx,
6427                                   session_info,
6428                                   msg_ctx,
6429                                   printer->sharename,
6430                                   SPOOL_DSSPOOLER_KEY,
6431                                   SPOOL_REG_SERVERNAME,
6432                                   REG_SZ,
6433                                   buffer.data,
6434                                   buffer.length);
6435
6436         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6437                                   global_myname(), printer->sharename);
6438         push_reg_sz(mem_ctx, &buffer, uncname);
6439         winreg_set_printer_dataex(mem_ctx,
6440                                   session_info,
6441                                   msg_ctx,
6442                                   printer->sharename,
6443                                   SPOOL_DSSPOOLER_KEY,
6444                                   SPOOL_REG_UNCNAME,
6445                                   REG_SZ,
6446                                   buffer.data,
6447                                   buffer.length);
6448
6449 done:
6450         return result;
6451 }
6452
6453 /********************************************************************
6454  * Called by spoolss_api_setprinter
6455  * when updating a printer description.
6456  ********************************************************************/
6457
6458 static WERROR update_printer(struct pipes_struct *p,
6459                              struct policy_handle *handle,
6460                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6461                              struct spoolss_DeviceMode *devmode)
6462 {
6463         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6464         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6465         struct spoolss_PrinterInfo2 *old_printer;
6466         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6467         int snum;
6468         WERROR result = WERR_OK;
6469         TALLOC_CTX *tmp_ctx;
6470
6471         DEBUG(8,("update_printer\n"));
6472
6473         tmp_ctx = talloc_new(p->mem_ctx);
6474         if (tmp_ctx == NULL) {
6475                 return WERR_NOMEM;
6476         }
6477
6478         if (!Printer) {
6479                 result = WERR_BADFID;
6480                 goto done;
6481         }
6482
6483         if (!get_printer_snum(p, handle, &snum, NULL)) {
6484                 result = WERR_BADFID;
6485                 goto done;
6486         }
6487
6488         result = winreg_get_printer(tmp_ctx,
6489                                     get_session_info_system(),
6490                                     p->msg_ctx,
6491                                     lp_const_servicename(snum),
6492                                     &old_printer);
6493         if (!W_ERROR_IS_OK(result)) {
6494                 result = WERR_BADFID;
6495                 goto done;
6496         }
6497
6498         /* Do sanity check on the requested changes for Samba */
6499         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6500                 result = WERR_INVALID_PARAM;
6501                 goto done;
6502         }
6503
6504         /* FIXME!!! If the driver has changed we really should verify that
6505            it is installed before doing much else   --jerry */
6506
6507         /* Check calling user has permission to update printer description */
6508         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6509                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6510                 result = WERR_ACCESS_DENIED;
6511                 goto done;
6512         }
6513
6514         /* Call addprinter hook */
6515         /* Check changes to see if this is really needed */
6516
6517         if (*lp_addprinter_cmd() &&
6518                         (!strequal(printer->drivername, old_printer->drivername) ||
6519                          !strequal(printer->comment, old_printer->comment) ||
6520                          !strequal(printer->portname, old_printer->portname) ||
6521                          !strequal(printer->location, old_printer->location)) )
6522         {
6523                 /* add_printer_hook() will call reload_services() */
6524                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6525                                       printer, p->client_id->addr,
6526                                       p->msg_ctx)) {
6527                         result = WERR_ACCESS_DENIED;
6528                         goto done;
6529                 }
6530         }
6531
6532         update_dsspooler(tmp_ctx,
6533                          get_session_info_system(),
6534                          p->msg_ctx,
6535                          snum,
6536                          printer,
6537                          old_printer);
6538
6539         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6540
6541         if (devmode == NULL) {
6542                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6543         }
6544         result = winreg_update_printer(tmp_ctx,
6545                                        get_session_info_system(),
6546                                        p->msg_ctx,
6547                                        printer->sharename,
6548                                        printer_mask,
6549                                        printer,
6550                                        devmode,
6551                                        NULL);
6552
6553 done:
6554         talloc_free(tmp_ctx);
6555
6556         return result;
6557 }
6558
6559 /****************************************************************************
6560 ****************************************************************************/
6561 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6562                                            struct policy_handle *handle,
6563                                            struct spoolss_SetPrinterInfo7 *info7)
6564 {
6565 #ifdef HAVE_ADS
6566         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6567         WERROR result;
6568         int snum;
6569         struct printer_handle *Printer;
6570
6571         if ( lp_security() != SEC_ADS ) {
6572                 return WERR_UNKNOWN_LEVEL;
6573         }
6574
6575         Printer = find_printer_index_by_hnd(p, handle);
6576
6577         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6578
6579         if (!Printer)
6580                 return WERR_BADFID;
6581
6582         if (!get_printer_snum(p, handle, &snum, NULL))
6583                 return WERR_BADFID;
6584
6585         result = winreg_get_printer(p->mem_ctx,
6586                                     get_session_info_system(),
6587                                     p->msg_ctx,
6588                                     lp_servicename(snum),
6589                                     &pinfo2);
6590         if (!W_ERROR_IS_OK(result)) {
6591                 return WERR_BADFID;
6592         }
6593
6594         nt_printer_publish(pinfo2,
6595                            get_session_info_system(),
6596                            p->msg_ctx,
6597                            pinfo2,
6598                            info7->action);
6599
6600         TALLOC_FREE(pinfo2);
6601         return WERR_OK;
6602 #else
6603         return WERR_UNKNOWN_LEVEL;
6604 #endif
6605 }
6606
6607 /********************************************************************
6608  ********************************************************************/
6609
6610 static WERROR update_printer_devmode(struct pipes_struct *p,
6611                                      struct policy_handle *handle,
6612                                      struct spoolss_DeviceMode *devmode)
6613 {
6614         int snum;
6615         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6616         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6617
6618         DEBUG(8,("update_printer_devmode\n"));
6619
6620         if (!Printer) {
6621                 return WERR_BADFID;
6622         }
6623
6624         if (!get_printer_snum(p, handle, &snum, NULL)) {
6625                 return WERR_BADFID;
6626         }
6627
6628         /* Check calling user has permission to update printer description */
6629         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6630                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6631                 return WERR_ACCESS_DENIED;
6632         }
6633
6634         return winreg_update_printer(p->mem_ctx,
6635                                      get_session_info_system(),
6636                                      p->msg_ctx,
6637                                      lp_const_servicename(snum),
6638                                      info2_mask,
6639                                      NULL,
6640                                      devmode,
6641                                      NULL);
6642 }
6643
6644
6645 /****************************************************************
6646  _spoolss_SetPrinter
6647 ****************************************************************/
6648
6649 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6650                            struct spoolss_SetPrinter *r)
6651 {
6652         WERROR result;
6653
6654         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6655
6656         if (!Printer) {
6657                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6658                         OUR_HANDLE(r->in.handle)));
6659                 return WERR_BADFID;
6660         }
6661
6662         /* check the level */
6663         switch (r->in.info_ctr->level) {
6664                 case 0:
6665                         return control_printer(r->in.handle, r->in.command, p);
6666                 case 2:
6667                         result = update_printer(p, r->in.handle,
6668                                                 r->in.info_ctr,
6669                                                 r->in.devmode_ctr->devmode);
6670                         if (!W_ERROR_IS_OK(result))
6671                                 return result;
6672                         if (r->in.secdesc_ctr->sd)
6673                                 result = update_printer_sec(r->in.handle, p,
6674                                                             r->in.secdesc_ctr);
6675                         return result;
6676                 case 3:
6677                         return update_printer_sec(r->in.handle, p,
6678                                                   r->in.secdesc_ctr);
6679                 case 7:
6680                         return publish_or_unpublish_printer(p, r->in.handle,
6681                                                             r->in.info_ctr->info.info7);
6682                 case 8:
6683                         return update_printer_devmode(p, r->in.handle,
6684                                                       r->in.devmode_ctr->devmode);
6685                 default:
6686                         return WERR_UNKNOWN_LEVEL;
6687         }
6688 }
6689
6690 /****************************************************************
6691  _spoolss_FindClosePrinterNotify
6692 ****************************************************************/
6693
6694 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6695                                        struct spoolss_FindClosePrinterNotify *r)
6696 {
6697         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6698
6699         if (!Printer) {
6700                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6701                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6702                 return WERR_BADFID;
6703         }
6704
6705         if (Printer->notify.cli_chan != NULL &&
6706             Printer->notify.cli_chan->active_connections > 0) {
6707                 int snum = -1;
6708
6709                 if (Printer->printer_type == SPLHND_PRINTER) {
6710                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6711                                 return WERR_BADFID;
6712                         }
6713                 }
6714
6715                 srv_spoolss_replycloseprinter(snum, Printer);
6716         }
6717
6718         Printer->notify.flags=0;
6719         Printer->notify.options=0;
6720         Printer->notify.localmachine[0]='\0';
6721         Printer->notify.printerlocal=0;
6722         TALLOC_FREE(Printer->notify.option);
6723
6724         return WERR_OK;
6725 }
6726
6727 /****************************************************************
6728  _spoolss_AddJob
6729 ****************************************************************/
6730
6731 WERROR _spoolss_AddJob(struct pipes_struct *p,
6732                        struct spoolss_AddJob *r)
6733 {
6734         if (!r->in.buffer && (r->in.offered != 0)) {
6735                 return WERR_INVALID_PARAM;
6736         }
6737
6738         /* this is what a NT server returns for AddJob. AddJob must fail on
6739          * non-local printers */
6740
6741         if (r->in.level != 1) {
6742                 return WERR_UNKNOWN_LEVEL;
6743         }
6744
6745         return WERR_INVALID_PARAM;
6746 }
6747
6748 /****************************************************************************
6749 fill_job_info1
6750 ****************************************************************************/
6751
6752 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6753                              struct spoolss_JobInfo1 *r,
6754                              const print_queue_struct *queue,
6755                              int position, int snum,
6756                              struct spoolss_PrinterInfo2 *pinfo2)
6757 {
6758         struct tm *t;
6759
6760         t = gmtime(&queue->time);
6761
6762         r->job_id               = queue->job;
6763
6764         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6765         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6766         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6767         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6768         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6769         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6770         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6771         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6772         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6773         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6774         r->text_status          = talloc_strdup(mem_ctx, "");
6775         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6776
6777         r->status               = nt_printj_status(queue->status);
6778         r->priority             = queue->priority;
6779         r->position             = position;
6780         r->total_pages          = queue->page_count;
6781         r->pages_printed        = 0; /* ??? */
6782
6783         init_systemtime(&r->submitted, t);
6784
6785         return WERR_OK;
6786 }
6787
6788 /****************************************************************************
6789 fill_job_info2
6790 ****************************************************************************/
6791
6792 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6793                              struct spoolss_JobInfo2 *r,
6794                              const print_queue_struct *queue,
6795                              int position, int snum,
6796                              struct spoolss_PrinterInfo2 *pinfo2,
6797                              struct spoolss_DeviceMode *devmode)
6798 {
6799         struct tm *t;
6800
6801         t = gmtime(&queue->time);
6802
6803         r->job_id               = queue->job;
6804
6805         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6806         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6807         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6808         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6809         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6810         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6811         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6812         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6813         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6814         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6815         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6816         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6817         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6818         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6819         r->parameters           = talloc_strdup(mem_ctx, "");
6820         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6821         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6822         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6823
6824         r->devmode              = devmode;
6825
6826         r->text_status          = talloc_strdup(mem_ctx, "");
6827         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6828
6829         r->secdesc              = NULL;
6830
6831         r->status               = nt_printj_status(queue->status);
6832         r->priority             = queue->priority;
6833         r->position             = position;
6834         r->start_time           = 0;
6835         r->until_time           = 0;
6836         r->total_pages          = queue->page_count;
6837         r->size                 = queue->size;
6838         init_systemtime(&r->submitted, t);
6839         r->time                 = 0;
6840         r->pages_printed        = 0; /* ??? */
6841
6842         return WERR_OK;
6843 }
6844
6845 /****************************************************************************
6846 fill_job_info3
6847 ****************************************************************************/
6848
6849 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6850                              struct spoolss_JobInfo3 *r,
6851                              const print_queue_struct *queue,
6852                              const print_queue_struct *next_queue,
6853                              int position, int snum,
6854                              struct spoolss_PrinterInfo2 *pinfo2)
6855 {
6856         r->job_id               = queue->job;
6857         r->next_job_id          = 0;
6858         if (next_queue) {
6859                 r->next_job_id  = next_queue->job;
6860         }
6861         r->reserved             = 0;
6862
6863         return WERR_OK;
6864 }
6865
6866 /****************************************************************************
6867  Enumjobs at level 1.
6868 ****************************************************************************/
6869
6870 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6871                               const print_queue_struct *queue,
6872                               uint32_t num_queues, int snum,
6873                               struct spoolss_PrinterInfo2 *pinfo2,
6874                               union spoolss_JobInfo **info_p,
6875                               uint32_t *count)
6876 {
6877         union spoolss_JobInfo *info;
6878         int i;
6879         WERROR result = WERR_OK;
6880
6881         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6882         W_ERROR_HAVE_NO_MEMORY(info);
6883
6884         *count = num_queues;
6885
6886         for (i=0; i<*count; i++) {
6887                 result = fill_job_info1(info,
6888                                         &info[i].info1,
6889                                         &queue[i],
6890                                         i,
6891                                         snum,
6892                                         pinfo2);
6893                 if (!W_ERROR_IS_OK(result)) {
6894                         goto out;
6895                 }
6896         }
6897
6898  out:
6899         if (!W_ERROR_IS_OK(result)) {
6900                 TALLOC_FREE(info);
6901                 *count = 0;
6902                 return result;
6903         }
6904
6905         *info_p = info;
6906
6907         return WERR_OK;
6908 }
6909
6910 /****************************************************************************
6911  Enumjobs at level 2.
6912 ****************************************************************************/
6913
6914 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6915                               const print_queue_struct *queue,
6916                               uint32_t num_queues, int snum,
6917                               struct spoolss_PrinterInfo2 *pinfo2,
6918                               union spoolss_JobInfo **info_p,
6919                               uint32_t *count)
6920 {
6921         union spoolss_JobInfo *info;
6922         int i;
6923         WERROR result = WERR_OK;
6924
6925         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6926         W_ERROR_HAVE_NO_MEMORY(info);
6927
6928         *count = num_queues;
6929
6930         for (i=0; i<*count; i++) {
6931                 struct spoolss_DeviceMode *devmode;
6932
6933                 result = spoolss_create_default_devmode(info,
6934                                                         pinfo2->printername,
6935                                                         &devmode);
6936                 if (!W_ERROR_IS_OK(result)) {
6937                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6938                         goto out;
6939                 }
6940
6941                 result = fill_job_info2(info,
6942                                         &info[i].info2,
6943                                         &queue[i],
6944                                         i,
6945                                         snum,
6946                                         pinfo2,
6947                                         devmode);
6948                 if (!W_ERROR_IS_OK(result)) {
6949                         goto out;
6950                 }
6951         }
6952
6953  out:
6954         if (!W_ERROR_IS_OK(result)) {
6955                 TALLOC_FREE(info);
6956                 *count = 0;
6957                 return result;
6958         }
6959
6960         *info_p = info;
6961
6962         return WERR_OK;
6963 }
6964
6965 /****************************************************************************
6966  Enumjobs at level 3.
6967 ****************************************************************************/
6968
6969 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6970                               const print_queue_struct *queue,
6971                               uint32_t num_queues, int snum,
6972                               struct spoolss_PrinterInfo2 *pinfo2,
6973                               union spoolss_JobInfo **info_p,
6974                               uint32_t *count)
6975 {
6976         union spoolss_JobInfo *info;
6977         int i;
6978         WERROR result = WERR_OK;
6979
6980         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6981         W_ERROR_HAVE_NO_MEMORY(info);
6982
6983         *count = num_queues;
6984
6985         for (i=0; i<*count; i++) {
6986                 const print_queue_struct *next_queue = NULL;
6987
6988                 if (i+1 < *count) {
6989                         next_queue = &queue[i+1];
6990                 }
6991
6992                 result = fill_job_info3(info,
6993                                         &info[i].info3,
6994                                         &queue[i],
6995                                         next_queue,
6996                                         i,
6997                                         snum,
6998                                         pinfo2);
6999                 if (!W_ERROR_IS_OK(result)) {
7000                         goto out;
7001                 }
7002         }
7003
7004  out:
7005         if (!W_ERROR_IS_OK(result)) {
7006                 TALLOC_FREE(info);
7007                 *count = 0;
7008                 return result;
7009         }
7010
7011         *info_p = info;
7012
7013         return WERR_OK;
7014 }
7015
7016 /****************************************************************
7017  _spoolss_EnumJobs
7018 ****************************************************************/
7019
7020 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7021                          struct spoolss_EnumJobs *r)
7022 {
7023         WERROR result;
7024         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7025         int snum;
7026         print_status_struct prt_status;
7027         print_queue_struct *queue = NULL;
7028         uint32_t count;
7029
7030         /* that's an [in out] buffer */
7031
7032         if (!r->in.buffer && (r->in.offered != 0)) {
7033                 return WERR_INVALID_PARAM;
7034         }
7035
7036         DEBUG(4,("_spoolss_EnumJobs\n"));
7037
7038         *r->out.needed = 0;
7039         *r->out.count = 0;
7040         *r->out.info = NULL;
7041
7042         /* lookup the printer snum and tdb entry */
7043
7044         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7045                 return WERR_BADFID;
7046         }
7047
7048         result = winreg_get_printer(p->mem_ctx,
7049                                     get_session_info_system(),
7050                                     p->msg_ctx,
7051                                     lp_const_servicename(snum),
7052                                     &pinfo2);
7053         if (!W_ERROR_IS_OK(result)) {
7054                 return result;
7055         }
7056
7057         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7058         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7059                 count, prt_status.status, prt_status.message));
7060
7061         if (count == 0) {
7062                 SAFE_FREE(queue);
7063                 TALLOC_FREE(pinfo2);
7064                 return WERR_OK;
7065         }
7066
7067         switch (r->in.level) {
7068         case 1:
7069                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7070                                          pinfo2, r->out.info, r->out.count);
7071                 break;
7072         case 2:
7073                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7074                                          pinfo2, r->out.info, r->out.count);
7075                 break;
7076         case 3:
7077                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7078                                          pinfo2, r->out.info, r->out.count);
7079                 break;
7080         default:
7081                 result = WERR_UNKNOWN_LEVEL;
7082                 break;
7083         }
7084
7085         SAFE_FREE(queue);
7086         TALLOC_FREE(pinfo2);
7087
7088         if (!W_ERROR_IS_OK(result)) {
7089                 return result;
7090         }
7091
7092         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7093                                                      spoolss_EnumJobs,
7094                                                      *r->out.info, r->in.level,
7095                                                      *r->out.count);
7096         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7097         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7098
7099         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7100 }
7101
7102 /****************************************************************
7103  _spoolss_ScheduleJob
7104 ****************************************************************/
7105
7106 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7107                             struct spoolss_ScheduleJob *r)
7108 {
7109         return WERR_OK;
7110 }
7111
7112 /****************************************************************
7113 ****************************************************************/
7114
7115 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7116                                struct messaging_context *msg_ctx,
7117                                const char *printer_name,
7118                                uint32_t job_id,
7119                                struct spoolss_SetJobInfo1 *r)
7120 {
7121         char *old_doc_name;
7122
7123         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7124                 return WERR_BADFID;
7125         }
7126
7127         if (strequal(old_doc_name, r->document_name)) {
7128                 return WERR_OK;
7129         }
7130
7131         if (!print_job_set_name(server_event_context(), msg_ctx,
7132                                 printer_name, job_id, r->document_name)) {
7133                 return WERR_BADFID;
7134         }
7135
7136         return WERR_OK;
7137 }
7138
7139 /****************************************************************
7140  _spoolss_SetJob
7141 ****************************************************************/
7142
7143 WERROR _spoolss_SetJob(struct pipes_struct *p,
7144                        struct spoolss_SetJob *r)
7145 {
7146         const struct auth_serversupplied_info *session_info = p->session_info;
7147         int snum;
7148         WERROR errcode = WERR_BADFUNC;
7149
7150         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7151                 return WERR_BADFID;
7152         }
7153
7154         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7155                 return WERR_INVALID_PRINTER_NAME;
7156         }
7157
7158         switch (r->in.command) {
7159         case SPOOLSS_JOB_CONTROL_CANCEL:
7160         case SPOOLSS_JOB_CONTROL_DELETE:
7161                 errcode = print_job_delete(session_info, p->msg_ctx,
7162                                            snum, r->in.job_id);
7163                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7164                         errcode = WERR_OK;
7165                 }
7166                 break;
7167         case SPOOLSS_JOB_CONTROL_PAUSE:
7168                 if (print_job_pause(session_info, p->msg_ctx,
7169                                     snum, r->in.job_id, &errcode)) {
7170                         errcode = WERR_OK;
7171                 }
7172                 break;
7173         case SPOOLSS_JOB_CONTROL_RESTART:
7174         case SPOOLSS_JOB_CONTROL_RESUME:
7175                 if (print_job_resume(session_info, p->msg_ctx,
7176                                      snum, r->in.job_id, &errcode)) {
7177                         errcode = WERR_OK;
7178                 }
7179                 break;
7180         case 0:
7181                 errcode = WERR_OK;
7182                 break;
7183         default:
7184                 return WERR_UNKNOWN_LEVEL;
7185         }
7186
7187         if (!W_ERROR_IS_OK(errcode)) {
7188                 return errcode;
7189         }
7190
7191         if (r->in.ctr == NULL) {
7192                 return errcode;
7193         }
7194
7195         switch (r->in.ctr->level) {
7196         case 1:
7197                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7198                                            lp_const_servicename(snum),
7199                                            r->in.job_id,
7200                                            r->in.ctr->info.info1);
7201                 break;
7202         case 2:
7203         case 3:
7204         case 4:
7205         default:
7206                 return WERR_UNKNOWN_LEVEL;
7207         }
7208
7209         return errcode;
7210 }
7211
7212 /****************************************************************************
7213  Enumerates all printer drivers by level and architecture.
7214 ****************************************************************************/
7215
7216 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7217                                                        const struct auth_serversupplied_info *session_info,
7218                                                        struct messaging_context *msg_ctx,
7219                                                        const char *servername,
7220                                                        const char *architecture,
7221                                                        uint32_t level,
7222                                                        union spoolss_DriverInfo **info_p,
7223                                                        uint32_t *count_p)
7224 {
7225         int i;
7226         uint32_t version;
7227         struct spoolss_DriverInfo8 *driver;
7228         union spoolss_DriverInfo *info = NULL;
7229         uint32_t count = 0;
7230         WERROR result = WERR_OK;
7231         uint32_t num_drivers;
7232         const char **drivers;
7233
7234         *count_p = 0;
7235         *info_p = NULL;
7236
7237         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7238                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7239                                                 architecture, version,
7240                                                 &num_drivers, &drivers);
7241                 if (!W_ERROR_IS_OK(result)) {
7242                         goto out;
7243                 }
7244                 DEBUG(4, ("we have:[%d] drivers in environment"
7245                           " [%s] and version [%d]\n",
7246                           num_drivers, architecture, version));
7247
7248                 if (num_drivers != 0) {
7249                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7250                                                     union spoolss_DriverInfo,
7251                                                     count + num_drivers);
7252                         if (!info) {
7253                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7254                                         "failed to enlarge driver info buffer!\n"));
7255                                 result = WERR_NOMEM;
7256                                 goto out;
7257                         }
7258                 }
7259
7260                 for (i = 0; i < num_drivers; i++) {
7261                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7262
7263                         result = winreg_get_driver(mem_ctx, session_info,
7264                                                    msg_ctx,
7265                                                    architecture, drivers[i],
7266                                                    version, &driver);
7267                         if (!W_ERROR_IS_OK(result)) {
7268                                 goto out;
7269                         }
7270
7271                         switch (level) {
7272                         case 1:
7273                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7274                                                                    driver, servername);
7275                                 break;
7276                         case 2:
7277                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7278                                                                    driver, servername);
7279                                 break;
7280                         case 3:
7281                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7282                                                                    driver, servername);
7283                                 break;
7284                         case 4:
7285                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7286                                                                    driver, servername);
7287                                 break;
7288                         case 5:
7289                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7290                                                                    driver, servername);
7291                                 break;
7292                         case 6:
7293                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7294                                                                    driver, servername);
7295                                 break;
7296                         case 8:
7297                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7298                                                                    driver, servername);
7299                                 break;
7300                         default:
7301                                 result = WERR_UNKNOWN_LEVEL;
7302                                 break;
7303                         }
7304
7305                         TALLOC_FREE(driver);
7306
7307                         if (!W_ERROR_IS_OK(result)) {
7308                                 goto out;
7309                         }
7310                 }
7311
7312                 count += num_drivers;
7313                 TALLOC_FREE(drivers);
7314         }
7315
7316  out:
7317         TALLOC_FREE(drivers);
7318
7319         if (!W_ERROR_IS_OK(result)) {
7320                 TALLOC_FREE(info);
7321                 return result;
7322         }
7323
7324         *info_p = info;
7325         *count_p = count;
7326
7327         return WERR_OK;
7328 }
7329
7330 /****************************************************************************
7331  Enumerates all printer drivers by level.
7332 ****************************************************************************/
7333
7334 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7335                                        const struct auth_serversupplied_info *session_info,
7336                                        struct messaging_context *msg_ctx,
7337                                        const char *servername,
7338                                        const char *architecture,
7339                                        uint32_t level,
7340                                        union spoolss_DriverInfo **info_p,
7341                                        uint32_t *count_p)
7342 {
7343         uint32_t a,i;
7344         WERROR result = WERR_OK;
7345
7346         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7347
7348                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7349
7350                         union spoolss_DriverInfo *info = NULL;
7351                         uint32_t count = 0;
7352
7353                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7354                                                                           session_info,
7355                                                                           msg_ctx,
7356                                                                           servername,
7357                                                                           archi_table[a].long_archi,
7358                                                                           level,
7359                                                                           &info,
7360                                                                           &count);
7361                         if (!W_ERROR_IS_OK(result)) {
7362                                 continue;
7363                         }
7364
7365                         for (i=0; i < count; i++) {
7366                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7367                                              info[i], info_p, count_p);
7368                         }
7369                 }
7370
7371                 return result;
7372         }
7373
7374         return enumprinterdrivers_level_by_architecture(mem_ctx,
7375                                                         session_info,
7376                                                         msg_ctx,
7377                                                         servername,
7378                                                         architecture,
7379                                                         level,
7380                                                         info_p,
7381                                                         count_p);
7382 }
7383
7384 /****************************************************************
7385  _spoolss_EnumPrinterDrivers
7386 ****************************************************************/
7387
7388 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7389                                    struct spoolss_EnumPrinterDrivers *r)
7390 {
7391         const char *cservername;
7392         WERROR result;
7393
7394         /* that's an [in out] buffer */
7395
7396         if (!r->in.buffer && (r->in.offered != 0)) {
7397                 return WERR_INVALID_PARAM;
7398         }
7399
7400         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7401
7402         *r->out.needed = 0;
7403         *r->out.count = 0;
7404         *r->out.info = NULL;
7405
7406         cservername = canon_servername(r->in.server);
7407
7408         if (!is_myname_or_ipaddr(cservername)) {
7409                 return WERR_UNKNOWN_PRINTER_DRIVER;
7410         }
7411
7412         result = enumprinterdrivers_level(p->mem_ctx,
7413                                           get_session_info_system(),
7414                                           p->msg_ctx,
7415                                           cservername,
7416                                           r->in.environment,
7417                                           r->in.level,
7418                                           r->out.info,
7419                                           r->out.count);
7420         if (!W_ERROR_IS_OK(result)) {
7421                 return result;
7422         }
7423
7424         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7425                                                      spoolss_EnumPrinterDrivers,
7426                                                      *r->out.info, r->in.level,
7427                                                      *r->out.count);
7428         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7429         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7430
7431         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7432 }
7433
7434 /****************************************************************
7435  _spoolss_EnumForms
7436 ****************************************************************/
7437
7438 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7439                           struct spoolss_EnumForms *r)
7440 {
7441         WERROR result;
7442
7443         *r->out.count = 0;
7444         *r->out.needed = 0;
7445         *r->out.info = NULL;
7446
7447         /* that's an [in out] buffer */
7448
7449         if (!r->in.buffer && (r->in.offered != 0) ) {
7450                 return WERR_INVALID_PARAM;
7451         }
7452
7453         DEBUG(4,("_spoolss_EnumForms\n"));
7454         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7455         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7456
7457         switch (r->in.level) {
7458         case 1:
7459                 result = winreg_printer_enumforms1(p->mem_ctx,
7460                                                    get_session_info_system(),
7461                                                    p->msg_ctx,
7462                                                    r->out.count,
7463                                                    r->out.info);
7464                 break;
7465         default:
7466                 result = WERR_UNKNOWN_LEVEL;
7467                 break;
7468         }
7469
7470         if (!W_ERROR_IS_OK(result)) {
7471                 return result;
7472         }
7473
7474         if (*r->out.count == 0) {
7475                 return WERR_NO_MORE_ITEMS;
7476         }
7477
7478         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7479                                                      spoolss_EnumForms,
7480                                                      *r->out.info, r->in.level,
7481                                                      *r->out.count);
7482         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7483         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7484
7485         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7486 }
7487
7488 /****************************************************************
7489  _spoolss_GetForm
7490 ****************************************************************/
7491
7492 WERROR _spoolss_GetForm(struct pipes_struct *p,
7493                         struct spoolss_GetForm *r)
7494 {
7495         WERROR result;
7496
7497         /* that's an [in out] buffer */
7498
7499         if (!r->in.buffer && (r->in.offered != 0)) {
7500                 return WERR_INVALID_PARAM;
7501         }
7502
7503         DEBUG(4,("_spoolss_GetForm\n"));
7504         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7505         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7506
7507         switch (r->in.level) {
7508         case 1:
7509                 result = winreg_printer_getform1(p->mem_ctx,
7510                                                  get_session_info_system(),
7511                                                  p->msg_ctx,
7512                                                  r->in.form_name,
7513                                                  &r->out.info->info1);
7514                 break;
7515         default:
7516                 result = WERR_UNKNOWN_LEVEL;
7517                 break;
7518         }
7519
7520         if (!W_ERROR_IS_OK(result)) {
7521                 TALLOC_FREE(r->out.info);
7522                 return result;
7523         }
7524
7525         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7526                                                r->out.info, r->in.level);
7527         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7528
7529         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7530 }
7531
7532 /****************************************************************************
7533 ****************************************************************************/
7534
7535 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7536                           struct spoolss_PortInfo1 *r,
7537                           const char *name)
7538 {
7539         r->port_name = talloc_strdup(mem_ctx, name);
7540         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7541
7542         return WERR_OK;
7543 }
7544
7545 /****************************************************************************
7546  TODO: This probably needs distinguish between TCP/IP and Local ports
7547  somehow.
7548 ****************************************************************************/
7549
7550 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7551                           struct spoolss_PortInfo2 *r,
7552                           const char *name)
7553 {
7554         r->port_name = talloc_strdup(mem_ctx, name);
7555         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7556
7557         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7558         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7559
7560         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7561         W_ERROR_HAVE_NO_MEMORY(r->description);
7562
7563         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7564         r->reserved = 0;
7565
7566         return WERR_OK;
7567 }
7568
7569
7570 /****************************************************************************
7571  wrapper around the enumer ports command
7572 ****************************************************************************/
7573
7574 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7575 {
7576         char *cmd = lp_enumports_cmd();
7577         char **qlines = NULL;
7578         char *command = NULL;
7579         int numlines;
7580         int ret;
7581         int fd;
7582
7583         *count = 0;
7584         *lines = NULL;
7585
7586         /* if no hook then just fill in the default port */
7587
7588         if ( !*cmd ) {
7589                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7590                         return WERR_NOMEM;
7591                 }
7592                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7593                         TALLOC_FREE(qlines);
7594                         return WERR_NOMEM;
7595                 }
7596                 qlines[1] = NULL;
7597                 numlines = 1;
7598         }
7599         else {
7600                 /* we have a valid enumport command */
7601
7602                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7603                 if (!command) {
7604                         return WERR_NOMEM;
7605                 }
7606
7607                 DEBUG(10,("Running [%s]\n", command));
7608                 ret = smbrun(command, &fd);
7609                 DEBUG(10,("Returned [%d]\n", ret));
7610                 TALLOC_FREE(command);
7611                 if (ret != 0) {
7612                         if (fd != -1) {
7613                                 close(fd);
7614                         }
7615                         return WERR_ACCESS_DENIED;
7616                 }
7617
7618                 numlines = 0;
7619                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7620                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7621                 close(fd);
7622         }
7623
7624         *count = numlines;
7625         *lines = qlines;
7626
7627         return WERR_OK;
7628 }
7629
7630 /****************************************************************************
7631  enumports level 1.
7632 ****************************************************************************/
7633
7634 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7635                                 union spoolss_PortInfo **info_p,
7636                                 uint32_t *count)
7637 {
7638         union spoolss_PortInfo *info = NULL;
7639         int i=0;
7640         WERROR result = WERR_OK;
7641         char **qlines = NULL;
7642         int numlines = 0;
7643
7644         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7645         if (!W_ERROR_IS_OK(result)) {
7646                 goto out;
7647         }
7648
7649         if (numlines) {
7650                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7651                 if (!info) {
7652                         DEBUG(10,("Returning WERR_NOMEM\n"));
7653                         result = WERR_NOMEM;
7654                         goto out;
7655                 }
7656
7657                 for (i=0; i<numlines; i++) {
7658                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7659                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7660                         if (!W_ERROR_IS_OK(result)) {
7661                                 goto out;
7662                         }
7663                 }
7664         }
7665         TALLOC_FREE(qlines);
7666
7667 out:
7668         if (!W_ERROR_IS_OK(result)) {
7669                 TALLOC_FREE(info);
7670                 TALLOC_FREE(qlines);
7671                 *count = 0;
7672                 *info_p = NULL;
7673                 return result;
7674         }
7675
7676         *info_p = info;
7677         *count = numlines;
7678
7679         return WERR_OK;
7680 }
7681
7682 /****************************************************************************
7683  enumports level 2.
7684 ****************************************************************************/
7685
7686 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7687                                 union spoolss_PortInfo **info_p,
7688                                 uint32_t *count)
7689 {
7690         union spoolss_PortInfo *info = NULL;
7691         int i=0;
7692         WERROR result = WERR_OK;
7693         char **qlines = NULL;
7694         int numlines = 0;
7695
7696         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7697         if (!W_ERROR_IS_OK(result)) {
7698                 goto out;
7699         }
7700
7701         if (numlines) {
7702                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7703                 if (!info) {
7704                         DEBUG(10,("Returning WERR_NOMEM\n"));
7705                         result = WERR_NOMEM;
7706                         goto out;
7707                 }
7708
7709                 for (i=0; i<numlines; i++) {
7710                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7711                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7712                         if (!W_ERROR_IS_OK(result)) {
7713                                 goto out;
7714                         }
7715                 }
7716         }
7717         TALLOC_FREE(qlines);
7718
7719 out:
7720         if (!W_ERROR_IS_OK(result)) {
7721                 TALLOC_FREE(info);
7722                 TALLOC_FREE(qlines);
7723                 *count = 0;
7724                 *info_p = NULL;
7725                 return result;
7726         }
7727
7728         *info_p = info;
7729         *count = numlines;
7730
7731         return WERR_OK;
7732 }
7733
7734 /****************************************************************
7735  _spoolss_EnumPorts
7736 ****************************************************************/
7737
7738 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7739                           struct spoolss_EnumPorts *r)
7740 {
7741         WERROR result;
7742
7743         /* that's an [in out] buffer */
7744
7745         if (!r->in.buffer && (r->in.offered != 0)) {
7746                 return WERR_INVALID_PARAM;
7747         }
7748
7749         DEBUG(4,("_spoolss_EnumPorts\n"));
7750
7751         *r->out.count = 0;
7752         *r->out.needed = 0;
7753         *r->out.info = NULL;
7754
7755         switch (r->in.level) {
7756         case 1:
7757                 result = enumports_level_1(p->mem_ctx, r->out.info,
7758                                            r->out.count);
7759                 break;
7760         case 2:
7761                 result = enumports_level_2(p->mem_ctx, r->out.info,
7762                                            r->out.count);
7763                 break;
7764         default:
7765                 return WERR_UNKNOWN_LEVEL;
7766         }
7767
7768         if (!W_ERROR_IS_OK(result)) {
7769                 return result;
7770         }
7771
7772         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7773                                                      spoolss_EnumPorts,
7774                                                      *r->out.info, r->in.level,
7775                                                      *r->out.count);
7776         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7777         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7778
7779         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7780 }
7781
7782 /****************************************************************************
7783 ****************************************************************************/
7784
7785 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7786                                            const char *server,
7787                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7788                                            struct spoolss_DeviceMode *devmode,
7789                                            struct security_descriptor *secdesc,
7790                                            struct spoolss_UserLevelCtr *user_ctr,
7791                                            struct policy_handle *handle)
7792 {
7793         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7794         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7795         int     snum;
7796         WERROR err = WERR_OK;
7797
7798         /* samba does not have a concept of local, non-shared printers yet, so
7799          * make sure we always setup sharename - gd */
7800         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7801             (info2->printername != NULL && info2->printername[0] != '\0')) {
7802                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7803                         "no sharename has been set, setting printername %s as sharename\n",
7804                         info2->printername));
7805                 info2->sharename = info2->printername;
7806         }
7807
7808         /* check to see if the printer already exists */
7809         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7810                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7811                         info2->sharename));
7812                 return WERR_PRINTER_ALREADY_EXISTS;
7813         }
7814
7815         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7816                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7817                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7818                                 info2->printername));
7819                         return WERR_PRINTER_ALREADY_EXISTS;
7820                 }
7821         }
7822
7823         /* validate printer info struct */
7824         if (!info2->printername || strlen(info2->printername) == 0) {
7825                 return WERR_INVALID_PRINTER_NAME;
7826         }
7827         if (!info2->portname || strlen(info2->portname) == 0) {
7828                 return WERR_UNKNOWN_PORT;
7829         }
7830         if (!info2->drivername || strlen(info2->drivername) == 0) {
7831                 return WERR_UNKNOWN_PRINTER_DRIVER;
7832         }
7833         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7834                 return WERR_UNKNOWN_PRINTPROCESSOR;
7835         }
7836
7837         /* FIXME!!!  smbd should check to see if the driver is installed before
7838            trying to add a printer like this  --jerry */
7839
7840         if (*lp_addprinter_cmd() ) {
7841                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7842                                        info2, p->client_id->addr,
7843                                        p->msg_ctx) ) {
7844                         return WERR_ACCESS_DENIED;
7845                 }
7846         } else {
7847                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7848                         "smb.conf parameter \"addprinter command\" is defined. This"
7849                         "parameter must exist for this call to succeed\n",
7850                         info2->sharename ));
7851         }
7852
7853         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7854                 return WERR_ACCESS_DENIED;
7855         }
7856
7857         /* you must be a printer admin to add a new printer */
7858         if (!print_access_check(p->session_info,
7859                                 p->msg_ctx,
7860                                 snum,
7861                                 PRINTER_ACCESS_ADMINISTER)) {
7862                 return WERR_ACCESS_DENIED;
7863         }
7864
7865         /*
7866          * Do sanity check on the requested changes for Samba.
7867          */
7868
7869         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7870                 return WERR_INVALID_PARAM;
7871         }
7872
7873         if (devmode == NULL) {
7874                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7875         }
7876
7877         update_dsspooler(p->mem_ctx,
7878                          get_session_info_system(),
7879                          p->msg_ctx,
7880                          0,
7881                          info2,
7882                          NULL);
7883
7884         err = winreg_update_printer(p->mem_ctx,
7885                                     get_session_info_system(),
7886                                     p->msg_ctx,
7887                                     info2->sharename,
7888                                     info2_mask,
7889                                     info2,
7890                                     devmode,
7891                                     secdesc);
7892         if (!W_ERROR_IS_OK(err)) {
7893                 return err;
7894         }
7895
7896         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7897         if (!W_ERROR_IS_OK(err)) {
7898                 /* Handle open failed - remove addition. */
7899                 ZERO_STRUCTP(handle);
7900                 return err;
7901         }
7902
7903         return WERR_OK;
7904 }
7905
7906 /****************************************************************
7907  _spoolss_AddPrinterEx
7908 ****************************************************************/
7909
7910 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7911                              struct spoolss_AddPrinterEx *r)
7912 {
7913         switch (r->in.info_ctr->level) {
7914         case 1:
7915                 /* we don't handle yet */
7916                 /* but I know what to do ... */
7917                 return WERR_UNKNOWN_LEVEL;
7918         case 2:
7919                 return spoolss_addprinterex_level_2(p, r->in.server,
7920                                                     r->in.info_ctr,
7921                                                     r->in.devmode_ctr->devmode,
7922                                                     r->in.secdesc_ctr->sd,
7923                                                     r->in.userlevel_ctr,
7924                                                     r->out.handle);
7925         default:
7926                 return WERR_UNKNOWN_LEVEL;
7927         }
7928 }
7929
7930 /****************************************************************
7931  _spoolss_AddPrinter
7932 ****************************************************************/
7933
7934 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7935                            struct spoolss_AddPrinter *r)
7936 {
7937         struct spoolss_AddPrinterEx a;
7938         struct spoolss_UserLevelCtr userlevel_ctr;
7939
7940         ZERO_STRUCT(userlevel_ctr);
7941
7942         userlevel_ctr.level = 1;
7943
7944         a.in.server             = r->in.server;
7945         a.in.info_ctr           = r->in.info_ctr;
7946         a.in.devmode_ctr        = r->in.devmode_ctr;
7947         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7948         a.in.userlevel_ctr      = &userlevel_ctr;
7949         a.out.handle            = r->out.handle;
7950
7951         return _spoolss_AddPrinterEx(p, &a);
7952 }
7953
7954 /****************************************************************
7955  _spoolss_AddPrinterDriverEx
7956 ****************************************************************/
7957
7958 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7959                                    struct spoolss_AddPrinterDriverEx *r)
7960 {
7961         WERROR err = WERR_OK;
7962         const char *driver_name = NULL;
7963         uint32_t version;
7964         const char *fn;
7965
7966         switch (p->opnum) {
7967                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7968                         fn = "_spoolss_AddPrinterDriver";
7969                         break;
7970                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7971                         fn = "_spoolss_AddPrinterDriverEx";
7972                         break;
7973                 default:
7974                         return WERR_INVALID_PARAM;
7975         }
7976
7977         /*
7978          * we only support the semantics of AddPrinterDriver()
7979          * i.e. only copy files that are newer than existing ones
7980          */
7981
7982         if (r->in.flags == 0) {
7983                 return WERR_INVALID_PARAM;
7984         }
7985
7986         if (r->in.flags != APD_COPY_NEW_FILES) {
7987                 return WERR_ACCESS_DENIED;
7988         }
7989
7990         /* FIXME */
7991         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7992                 /* Clever hack from Martin Zielinski <mz@seh.de>
7993                  * to allow downgrade from level 8 (Vista).
7994                  */
7995                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7996                         r->in.info_ctr->level));
7997                 return WERR_UNKNOWN_LEVEL;
7998         }
7999
8000         DEBUG(5,("Cleaning driver's information\n"));
8001         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8002         if (!W_ERROR_IS_OK(err))
8003                 goto done;
8004
8005         DEBUG(5,("Moving driver to final destination\n"));
8006         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
8007                                                               &err)) ) {
8008                 goto done;
8009         }
8010
8011         err = winreg_add_driver(p->mem_ctx,
8012                                 get_session_info_system(),
8013                                 p->msg_ctx,
8014                                 r->in.info_ctr,
8015                                 &driver_name,
8016                                 &version);
8017         if (!W_ERROR_IS_OK(err)) {
8018                 goto done;
8019         }
8020
8021         /*
8022          * I think this is where he DrvUpgradePrinter() hook would be
8023          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8024          * server.  Right now, we just need to send ourselves a message
8025          * to update each printer bound to this driver.   --jerry
8026          */
8027
8028         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8029                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8030                         fn, driver_name));
8031         }
8032
8033 done:
8034         return err;
8035 }
8036
8037 /****************************************************************
8038  _spoolss_AddPrinterDriver
8039 ****************************************************************/
8040
8041 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8042                                  struct spoolss_AddPrinterDriver *r)
8043 {
8044         struct spoolss_AddPrinterDriverEx a;
8045
8046         switch (r->in.info_ctr->level) {
8047         case 2:
8048         case 3:
8049         case 4:
8050         case 5:
8051                 break;
8052         default:
8053                 return WERR_UNKNOWN_LEVEL;
8054         }
8055
8056         a.in.servername         = r->in.servername;
8057         a.in.info_ctr           = r->in.info_ctr;
8058         a.in.flags              = APD_COPY_NEW_FILES;
8059
8060         return _spoolss_AddPrinterDriverEx(p, &a);
8061 }
8062
8063 /****************************************************************************
8064 ****************************************************************************/
8065
8066 struct _spoolss_paths {
8067         int type;
8068         const char *share;
8069         const char *dir;
8070 };
8071
8072 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8073
8074 static const struct _spoolss_paths spoolss_paths[]= {
8075         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8076         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8077 };
8078
8079 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8080                                           const char *servername,
8081                                           const char *environment,
8082                                           int component,
8083                                           char **path)
8084 {
8085         const char *pservername = NULL;
8086         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8087         const char *short_archi;
8088
8089         *path = NULL;
8090
8091         /* environment may be empty */
8092         if (environment && strlen(environment)) {
8093                 long_archi = environment;
8094         }
8095
8096         /* servername may be empty */
8097         if (servername && strlen(servername)) {
8098                 pservername = canon_servername(servername);
8099
8100                 if (!is_myname_or_ipaddr(pservername)) {
8101                         return WERR_INVALID_PARAM;
8102                 }
8103         }
8104
8105         if (!(short_archi = get_short_archi(long_archi))) {
8106                 return WERR_INVALID_ENVIRONMENT;
8107         }
8108
8109         switch (component) {
8110         case SPOOLSS_PRTPROCS_PATH:
8111         case SPOOLSS_DRIVER_PATH:
8112                 if (pservername) {
8113                         *path = talloc_asprintf(mem_ctx,
8114                                         "\\\\%s\\%s\\%s",
8115                                         pservername,
8116                                         spoolss_paths[component].share,
8117                                         short_archi);
8118                 } else {
8119                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8120                                         SPOOLSS_DEFAULT_SERVER_PATH,
8121                                         spoolss_paths[component].dir,
8122                                         short_archi);
8123                 }
8124                 break;
8125         default:
8126                 return WERR_INVALID_PARAM;
8127         }
8128
8129         if (!*path) {
8130                 return WERR_NOMEM;
8131         }
8132
8133         return WERR_OK;
8134 }
8135
8136 /****************************************************************************
8137 ****************************************************************************/
8138
8139 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8140                                           const char *servername,
8141                                           const char *environment,
8142                                           struct spoolss_DriverDirectoryInfo1 *r)
8143 {
8144         WERROR werr;
8145         char *path = NULL;
8146
8147         werr = compose_spoolss_server_path(mem_ctx,
8148                                            servername,
8149                                            environment,
8150                                            SPOOLSS_DRIVER_PATH,
8151                                            &path);
8152         if (!W_ERROR_IS_OK(werr)) {
8153                 return werr;
8154         }
8155
8156         DEBUG(4,("printer driver directory: [%s]\n", path));
8157
8158         r->directory_name = path;
8159
8160         return WERR_OK;
8161 }
8162
8163 /****************************************************************
8164  _spoolss_GetPrinterDriverDirectory
8165 ****************************************************************/
8166
8167 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8168                                           struct spoolss_GetPrinterDriverDirectory *r)
8169 {
8170         WERROR werror;
8171
8172         /* that's an [in out] buffer */
8173
8174         if (!r->in.buffer && (r->in.offered != 0)) {
8175                 return WERR_INVALID_PARAM;
8176         }
8177
8178         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8179                 r->in.level));
8180
8181         *r->out.needed = 0;
8182
8183         /* r->in.level is ignored */
8184
8185         werror = getprinterdriverdir_level_1(p->mem_ctx,
8186                                              r->in.server,
8187                                              r->in.environment,
8188                                              &r->out.info->info1);
8189         if (!W_ERROR_IS_OK(werror)) {
8190                 TALLOC_FREE(r->out.info);
8191                 return werror;
8192         }
8193
8194         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8195                                                r->out.info, r->in.level);
8196         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8197
8198         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8199 }
8200
8201 /****************************************************************
8202  _spoolss_EnumPrinterData
8203 ****************************************************************/
8204
8205 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8206                                 struct spoolss_EnumPrinterData *r)
8207 {
8208         WERROR result;
8209         struct spoolss_EnumPrinterDataEx r2;
8210         uint32_t count;
8211         struct spoolss_PrinterEnumValues *info, *val = NULL;
8212         uint32_t needed;
8213
8214         r2.in.handle    = r->in.handle;
8215         r2.in.key_name  = "PrinterDriverData";
8216         r2.in.offered   = 0;
8217         r2.out.count    = &count;
8218         r2.out.info     = &info;
8219         r2.out.needed   = &needed;
8220
8221         result = _spoolss_EnumPrinterDataEx(p, &r2);
8222         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8223                 r2.in.offered = needed;
8224                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8225         }
8226         if (!W_ERROR_IS_OK(result)) {
8227                 return result;
8228         }
8229
8230         /*
8231          * The NT machine wants to know the biggest size of value and data
8232          *
8233          * cf: MSDN EnumPrinterData remark section
8234          */
8235
8236         if (!r->in.value_offered && !r->in.data_offered) {
8237                 uint32_t biggest_valuesize = 0;
8238                 uint32_t biggest_datasize = 0;
8239                 int i, name_length;
8240
8241                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8242
8243                 for (i=0; i<count; i++) {
8244
8245                         name_length = strlen(info[i].value_name);
8246                         if (strlen(info[i].value_name) > biggest_valuesize) {
8247                                 biggest_valuesize = name_length;
8248                         }
8249
8250                         if (info[i].data_length > biggest_datasize) {
8251                                 biggest_datasize = info[i].data_length;
8252                         }
8253
8254                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8255                                 biggest_datasize));
8256                 }
8257
8258                 /* the value is an UNICODE string but real_value_size is the length
8259                    in bytes including the trailing 0 */
8260
8261                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8262                 *r->out.data_needed  = biggest_datasize;
8263
8264                 DEBUG(6,("final values: [%d], [%d]\n",
8265                         *r->out.value_needed, *r->out.data_needed));
8266
8267                 return WERR_OK;
8268         }
8269
8270         if (r->in.enum_index < count) {
8271                 val = &info[r->in.enum_index];
8272         }
8273
8274         if (val == NULL) {
8275                 /* out_value should default to "" or else NT4 has
8276                    problems unmarshalling the response */
8277
8278                 if (r->in.value_offered) {
8279                         *r->out.value_needed = 1;
8280                         r->out.value_name = talloc_strdup(r, "");
8281                         if (!r->out.value_name) {
8282                                 return WERR_NOMEM;
8283                         }
8284                 } else {
8285                         r->out.value_name = NULL;
8286                         *r->out.value_needed = 0;
8287                 }
8288
8289                 /* the data is counted in bytes */
8290
8291                 *r->out.data_needed = r->in.data_offered;
8292
8293                 result = WERR_NO_MORE_ITEMS;
8294         } else {
8295                 /*
8296                  * the value is:
8297                  * - counted in bytes in the request
8298                  * - counted in UNICODE chars in the max reply
8299                  * - counted in bytes in the real size
8300                  *
8301                  * take a pause *before* coding not *during* coding
8302                  */
8303
8304                 /* name */
8305                 if (r->in.value_offered) {
8306                         r->out.value_name = talloc_strdup(r, val->value_name);
8307                         if (!r->out.value_name) {
8308                                 return WERR_NOMEM;
8309                         }
8310                         *r->out.value_needed = val->value_name_len;
8311                 } else {
8312                         r->out.value_name = NULL;
8313                         *r->out.value_needed = 0;
8314                 }
8315
8316                 /* type */
8317
8318                 *r->out.type = val->type;
8319
8320                 /* data - counted in bytes */
8321
8322                 /*
8323                  * See the section "Dynamically Typed Query Parameters"
8324                  * in MS-RPRN.
8325                  */
8326
8327                 if (r->out.data && val->data && val->data->data &&
8328                                 val->data_length && r->in.data_offered) {
8329                         memcpy(r->out.data, val->data->data,
8330                                 MIN(val->data_length,r->in.data_offered));
8331                 }
8332
8333                 *r->out.data_needed = val->data_length;
8334
8335                 result = WERR_OK;
8336         }
8337
8338         return result;
8339 }
8340
8341 /****************************************************************
8342  _spoolss_SetPrinterData
8343 ****************************************************************/
8344
8345 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8346                                struct spoolss_SetPrinterData *r)
8347 {
8348         struct spoolss_SetPrinterDataEx r2;
8349
8350         r2.in.handle            = r->in.handle;
8351         r2.in.key_name          = "PrinterDriverData";
8352         r2.in.value_name        = r->in.value_name;
8353         r2.in.type              = r->in.type;
8354         r2.in.data              = r->in.data;
8355         r2.in.offered           = r->in.offered;
8356
8357         return _spoolss_SetPrinterDataEx(p, &r2);
8358 }
8359
8360 /****************************************************************
8361  _spoolss_ResetPrinter
8362 ****************************************************************/
8363
8364 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8365                              struct spoolss_ResetPrinter *r)
8366 {
8367         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8368         int             snum;
8369
8370         DEBUG(5,("_spoolss_ResetPrinter\n"));
8371
8372         /*
8373          * All we do is to check to see if the handle and queue is valid.
8374          * This call really doesn't mean anything to us because we only
8375          * support RAW printing.   --jerry
8376          */
8377
8378         if (!Printer) {
8379                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8380                         OUR_HANDLE(r->in.handle)));
8381                 return WERR_BADFID;
8382         }
8383
8384         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8385                 return WERR_BADFID;
8386
8387
8388         /* blindly return success */
8389         return WERR_OK;
8390 }
8391
8392 /****************************************************************
8393  _spoolss_DeletePrinterData
8394 ****************************************************************/
8395
8396 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8397                                   struct spoolss_DeletePrinterData *r)
8398 {
8399         struct spoolss_DeletePrinterDataEx r2;
8400
8401         r2.in.handle            = r->in.handle;
8402         r2.in.key_name          = "PrinterDriverData";
8403         r2.in.value_name        = r->in.value_name;
8404
8405         return _spoolss_DeletePrinterDataEx(p, &r2);
8406 }
8407
8408 /****************************************************************
8409  _spoolss_AddForm
8410 ****************************************************************/
8411
8412 WERROR _spoolss_AddForm(struct pipes_struct *p,
8413                         struct spoolss_AddForm *r)
8414 {
8415         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8416         int snum = -1;
8417         WERROR status = WERR_OK;
8418
8419         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8420
8421         DEBUG(5,("_spoolss_AddForm\n"));
8422
8423         if (!Printer) {
8424                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8425                         OUR_HANDLE(r->in.handle)));
8426                 return WERR_BADFID;
8427         }
8428
8429         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8430            and not a printer admin, then fail */
8431
8432         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8433             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8434             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8435                                           p->session_info->info3->base.domain.string,
8436                                           NULL,
8437                                           p->session_info->security_token,
8438                                           lp_printer_admin(snum))) {
8439                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8440                 return WERR_ACCESS_DENIED;
8441         }
8442
8443         switch (form->flags) {
8444         case SPOOLSS_FORM_USER:
8445         case SPOOLSS_FORM_BUILTIN:
8446         case SPOOLSS_FORM_PRINTER:
8447                 break;
8448         default:
8449                 return WERR_INVALID_PARAM;
8450         }
8451
8452         status = winreg_printer_addform1(p->mem_ctx,
8453                                          get_session_info_system(),
8454                                          p->msg_ctx,
8455                                          form);
8456         if (!W_ERROR_IS_OK(status)) {
8457                 return status;
8458         }
8459
8460         /*
8461          * ChangeID must always be set if this is a printer
8462          */
8463         if (Printer->printer_type == SPLHND_PRINTER) {
8464                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8465                         return WERR_BADFID;
8466                 }
8467
8468                 status = winreg_printer_update_changeid(p->mem_ctx,
8469                                                         get_session_info_system(),
8470                                                         p->msg_ctx,
8471                                                         lp_const_servicename(snum));
8472                 if (!W_ERROR_IS_OK(status)) {
8473                         return status;
8474                 }
8475         }
8476
8477         return status;
8478 }
8479
8480 /****************************************************************
8481  _spoolss_DeleteForm
8482 ****************************************************************/
8483
8484 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8485                            struct spoolss_DeleteForm *r)
8486 {
8487         const char *form_name = r->in.form_name;
8488         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8489         int snum = -1;
8490         WERROR status = WERR_OK;
8491
8492         DEBUG(5,("_spoolss_DeleteForm\n"));
8493
8494         if (!Printer) {
8495                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8496                         OUR_HANDLE(r->in.handle)));
8497                 return WERR_BADFID;
8498         }
8499
8500         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8501             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8502             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8503                                           p->session_info->info3->base.domain.string,
8504                                           NULL,
8505                                           p->session_info->security_token,
8506                                           lp_printer_admin(snum))) {
8507                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8508                 return WERR_ACCESS_DENIED;
8509         }
8510
8511         status = winreg_printer_deleteform1(p->mem_ctx,
8512                                             get_session_info_system(),
8513                                             p->msg_ctx,
8514                                             form_name);
8515         if (!W_ERROR_IS_OK(status)) {
8516                 return status;
8517         }
8518
8519         /*
8520          * ChangeID must always be set if this is a printer
8521          */
8522         if (Printer->printer_type == SPLHND_PRINTER) {
8523                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8524                         return WERR_BADFID;
8525                 }
8526
8527                 status = winreg_printer_update_changeid(p->mem_ctx,
8528                                                         get_session_info_system(),
8529                                                         p->msg_ctx,
8530                                                         lp_const_servicename(snum));
8531                 if (!W_ERROR_IS_OK(status)) {
8532                         return status;
8533                 }
8534         }
8535
8536         return status;
8537 }
8538
8539 /****************************************************************
8540  _spoolss_SetForm
8541 ****************************************************************/
8542
8543 WERROR _spoolss_SetForm(struct pipes_struct *p,
8544                         struct spoolss_SetForm *r)
8545 {
8546         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8547         const char *form_name = r->in.form_name;
8548         int snum = -1;
8549         WERROR status = WERR_OK;
8550
8551         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8552
8553         DEBUG(5,("_spoolss_SetForm\n"));
8554
8555         if (!Printer) {
8556                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8557                         OUR_HANDLE(r->in.handle)));
8558                 return WERR_BADFID;
8559         }
8560
8561         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8562            and not a printer admin, then fail */
8563
8564         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8565              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8566              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8567                                           p->session_info->info3->base.domain.string,
8568                                           NULL,
8569                                           p->session_info->security_token,
8570                                           lp_printer_admin(snum))) {
8571                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8572                 return WERR_ACCESS_DENIED;
8573         }
8574
8575         status = winreg_printer_setform1(p->mem_ctx,
8576                                          get_session_info_system(),
8577                                          p->msg_ctx,
8578                                          form_name,
8579                                          form);
8580         if (!W_ERROR_IS_OK(status)) {
8581                 return status;
8582         }
8583
8584         /*
8585          * ChangeID must always be set if this is a printer
8586          */
8587         if (Printer->printer_type == SPLHND_PRINTER) {
8588                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8589                         return WERR_BADFID;
8590                 }
8591
8592                 status = winreg_printer_update_changeid(p->mem_ctx,
8593                                                         get_session_info_system(),
8594                                                         p->msg_ctx,
8595                                                         lp_const_servicename(snum));
8596                 if (!W_ERROR_IS_OK(status)) {
8597                         return status;
8598                 }
8599         }
8600
8601         return status;
8602 }
8603
8604 /****************************************************************************
8605  fill_print_processor1
8606 ****************************************************************************/
8607
8608 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8609                                     struct spoolss_PrintProcessorInfo1 *r,
8610                                     const char *print_processor_name)
8611 {
8612         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8613         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8614
8615         return WERR_OK;
8616 }
8617
8618 /****************************************************************************
8619  enumprintprocessors level 1.
8620 ****************************************************************************/
8621
8622 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8623                                           union spoolss_PrintProcessorInfo **info_p,
8624                                           uint32_t *count)
8625 {
8626         union spoolss_PrintProcessorInfo *info;
8627         WERROR result;
8628
8629         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8630         W_ERROR_HAVE_NO_MEMORY(info);
8631
8632         *count = 1;
8633
8634         result = fill_print_processor1(info, &info[0].info1, "winprint");
8635         if (!W_ERROR_IS_OK(result)) {
8636                 goto out;
8637         }
8638
8639  out:
8640         if (!W_ERROR_IS_OK(result)) {
8641                 TALLOC_FREE(info);
8642                 *count = 0;
8643                 return result;
8644         }
8645
8646         *info_p = info;
8647
8648         return WERR_OK;
8649 }
8650
8651 /****************************************************************
8652  _spoolss_EnumPrintProcessors
8653 ****************************************************************/
8654
8655 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8656                                     struct spoolss_EnumPrintProcessors *r)
8657 {
8658         WERROR result;
8659
8660         /* that's an [in out] buffer */
8661
8662         if (!r->in.buffer && (r->in.offered != 0)) {
8663                 return WERR_INVALID_PARAM;
8664         }
8665
8666         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8667
8668         /*
8669          * Enumerate the print processors ...
8670          *
8671          * Just reply with "winprint", to keep NT happy
8672          * and I can use my nice printer checker.
8673          */
8674
8675         *r->out.count = 0;
8676         *r->out.needed = 0;
8677         *r->out.info = NULL;
8678
8679         if (!get_short_archi(r->in.environment)) {
8680                 return WERR_INVALID_ENVIRONMENT;
8681         }
8682
8683         switch (r->in.level) {
8684         case 1:
8685                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8686                                                      r->out.count);
8687                 break;
8688         default:
8689                 return WERR_UNKNOWN_LEVEL;
8690         }
8691
8692         if (!W_ERROR_IS_OK(result)) {
8693                 return result;
8694         }
8695
8696         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8697                                                      spoolss_EnumPrintProcessors,
8698                                                      *r->out.info, r->in.level,
8699                                                      *r->out.count);
8700         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8701         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8702
8703         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8704 }
8705
8706 /****************************************************************************
8707  fill_printprocdatatype1
8708 ****************************************************************************/
8709
8710 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8711                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8712                                       const char *name_array)
8713 {
8714         r->name_array = talloc_strdup(mem_ctx, name_array);
8715         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8716
8717         return WERR_OK;
8718 }
8719
8720 /****************************************************************************
8721  enumprintprocdatatypes level 1.
8722 ****************************************************************************/
8723
8724 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8725                                              union spoolss_PrintProcDataTypesInfo **info_p,
8726                                              uint32_t *count)
8727 {
8728         WERROR result;
8729         union spoolss_PrintProcDataTypesInfo *info;
8730
8731         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8732         W_ERROR_HAVE_NO_MEMORY(info);
8733
8734         *count = 1;
8735
8736         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8737         if (!W_ERROR_IS_OK(result)) {
8738                 goto out;
8739         }
8740
8741  out:
8742         if (!W_ERROR_IS_OK(result)) {
8743                 TALLOC_FREE(info);
8744                 *count = 0;
8745                 return result;
8746         }
8747
8748         *info_p = info;
8749
8750         return WERR_OK;
8751 }
8752
8753 /****************************************************************
8754  _spoolss_EnumPrintProcDataTypes
8755 ****************************************************************/
8756
8757 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8758                                        struct spoolss_EnumPrintProcDataTypes *r)
8759 {
8760         WERROR result;
8761
8762         /* that's an [in out] buffer */
8763
8764         if (!r->in.buffer && (r->in.offered != 0)) {
8765                 return WERR_INVALID_PARAM;
8766         }
8767
8768         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8769
8770         *r->out.count = 0;
8771         *r->out.needed = 0;
8772         *r->out.info = NULL;
8773
8774         if (r->in.print_processor_name == NULL ||
8775             !strequal(r->in.print_processor_name, "winprint")) {
8776                 return WERR_UNKNOWN_PRINTPROCESSOR;
8777         }
8778
8779         switch (r->in.level) {
8780         case 1:
8781                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8782                                                         r->out.count);
8783                 break;
8784         default:
8785                 return WERR_UNKNOWN_LEVEL;
8786         }
8787
8788         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8789                                                      spoolss_EnumPrintProcDataTypes,
8790                                                      *r->out.info, r->in.level,
8791                                                      *r->out.count);
8792         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8793         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8794
8795         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8796 }
8797
8798 /****************************************************************************
8799  fill_monitor_1
8800 ****************************************************************************/
8801
8802 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8803                              struct spoolss_MonitorInfo1 *r,
8804                              const char *monitor_name)
8805 {
8806         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8807         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8808
8809         return WERR_OK;
8810 }
8811
8812 /****************************************************************************
8813  fill_monitor_2
8814 ****************************************************************************/
8815
8816 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8817                              struct spoolss_MonitorInfo2 *r,
8818                              const char *monitor_name,
8819                              const char *environment,
8820                              const char *dll_name)
8821 {
8822         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8823         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8824         r->environment                  = talloc_strdup(mem_ctx, environment);
8825         W_ERROR_HAVE_NO_MEMORY(r->environment);
8826         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8827         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8828
8829         return WERR_OK;
8830 }
8831
8832 /****************************************************************************
8833  enumprintmonitors level 1.
8834 ****************************************************************************/
8835
8836 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8837                                         union spoolss_MonitorInfo **info_p,
8838                                         uint32_t *count)
8839 {
8840         union spoolss_MonitorInfo *info;
8841         WERROR result = WERR_OK;
8842
8843         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8844         W_ERROR_HAVE_NO_MEMORY(info);
8845
8846         *count = 2;
8847
8848         result = fill_monitor_1(info, &info[0].info1,
8849                                 SPL_LOCAL_PORT);
8850         if (!W_ERROR_IS_OK(result)) {
8851                 goto out;
8852         }
8853
8854         result = fill_monitor_1(info, &info[1].info1,
8855                                 SPL_TCPIP_PORT);
8856         if (!W_ERROR_IS_OK(result)) {
8857                 goto out;
8858         }
8859
8860 out:
8861         if (!W_ERROR_IS_OK(result)) {
8862                 TALLOC_FREE(info);
8863                 *count = 0;
8864                 return result;
8865         }
8866
8867         *info_p = info;
8868
8869         return WERR_OK;
8870 }
8871
8872 /****************************************************************************
8873  enumprintmonitors level 2.
8874 ****************************************************************************/
8875
8876 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8877                                         union spoolss_MonitorInfo **info_p,
8878                                         uint32_t *count)
8879 {
8880         union spoolss_MonitorInfo *info;
8881         WERROR result = WERR_OK;
8882
8883         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8884         W_ERROR_HAVE_NO_MEMORY(info);
8885
8886         *count = 2;
8887
8888         result = fill_monitor_2(info, &info[0].info2,
8889                                 SPL_LOCAL_PORT,
8890                                 "Windows NT X86", /* FIXME */
8891                                 "localmon.dll");
8892         if (!W_ERROR_IS_OK(result)) {
8893                 goto out;
8894         }
8895
8896         result = fill_monitor_2(info, &info[1].info2,
8897                                 SPL_TCPIP_PORT,
8898                                 "Windows NT X86", /* FIXME */
8899                                 "tcpmon.dll");
8900         if (!W_ERROR_IS_OK(result)) {
8901                 goto out;
8902         }
8903
8904 out:
8905         if (!W_ERROR_IS_OK(result)) {
8906                 TALLOC_FREE(info);
8907                 *count = 0;
8908                 return result;
8909         }
8910
8911         *info_p = info;
8912
8913         return WERR_OK;
8914 }
8915
8916 /****************************************************************
8917  _spoolss_EnumMonitors
8918 ****************************************************************/
8919
8920 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8921                              struct spoolss_EnumMonitors *r)
8922 {
8923         WERROR result;
8924
8925         /* that's an [in out] buffer */
8926
8927         if (!r->in.buffer && (r->in.offered != 0)) {
8928                 return WERR_INVALID_PARAM;
8929         }
8930
8931         DEBUG(5,("_spoolss_EnumMonitors\n"));
8932
8933         /*
8934          * Enumerate the print monitors ...
8935          *
8936          * Just reply with "Local Port", to keep NT happy
8937          * and I can use my nice printer checker.
8938          */
8939
8940         *r->out.count = 0;
8941         *r->out.needed = 0;
8942         *r->out.info = NULL;
8943
8944         switch (r->in.level) {
8945         case 1:
8946                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8947                                                    r->out.count);
8948                 break;
8949         case 2:
8950                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8951                                                    r->out.count);
8952                 break;
8953         default:
8954                 return WERR_UNKNOWN_LEVEL;
8955         }
8956
8957         if (!W_ERROR_IS_OK(result)) {
8958                 return result;
8959         }
8960
8961         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8962                                                      spoolss_EnumMonitors,
8963                                                      *r->out.info, r->in.level,
8964                                                      *r->out.count);
8965         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8966         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8967
8968         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8969 }
8970
8971 /****************************************************************************
8972 ****************************************************************************/
8973
8974 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8975                              const print_queue_struct *queue,
8976                              int count, int snum,
8977                              struct spoolss_PrinterInfo2 *pinfo2,
8978                              uint32_t jobid,
8979                              struct spoolss_JobInfo1 *r)
8980 {
8981         int i = 0;
8982         bool found = false;
8983
8984         for (i=0; i<count; i++) {
8985                 if (queue[i].job == (int)jobid) {
8986                         found = true;
8987                         break;
8988                 }
8989         }
8990
8991         if (found == false) {
8992                 /* NT treats not found as bad param... yet another bad choice */
8993                 return WERR_INVALID_PARAM;
8994         }
8995
8996         return fill_job_info1(mem_ctx,
8997                               r,
8998                               &queue[i],
8999                               i,
9000                               snum,
9001                               pinfo2);
9002 }
9003
9004 /****************************************************************************
9005 ****************************************************************************/
9006
9007 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9008                              const print_queue_struct *queue,
9009                              int count, int snum,
9010                              struct spoolss_PrinterInfo2 *pinfo2,
9011                              uint32_t jobid,
9012                              struct spoolss_JobInfo2 *r)
9013 {
9014         int i = 0;
9015         bool found = false;
9016         struct spoolss_DeviceMode *devmode;
9017         WERROR result;
9018
9019         for (i=0; i<count; i++) {
9020                 if (queue[i].job == (int)jobid) {
9021                         found = true;
9022                         break;
9023                 }
9024         }
9025
9026         if (found == false) {
9027                 /* NT treats not found as bad param... yet another bad
9028                    choice */
9029                 return WERR_INVALID_PARAM;
9030         }
9031
9032         /*
9033          * if the print job does not have a DEVMODE associated with it,
9034          * just use the one for the printer. A NULL devicemode is not
9035          *  a failure condition
9036          */
9037
9038         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9039         if (!devmode) {
9040                 result = spoolss_create_default_devmode(mem_ctx,
9041                                                 pinfo2->printername,
9042                                                 &devmode);
9043                 if (!W_ERROR_IS_OK(result)) {
9044                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9045                         return result;
9046                 }
9047         }
9048
9049         return fill_job_info2(mem_ctx,
9050                               r,
9051                               &queue[i],
9052                               i,
9053                               snum,
9054                               pinfo2,
9055                               devmode);
9056 }
9057
9058 /****************************************************************
9059  _spoolss_GetJob
9060 ****************************************************************/
9061
9062 WERROR _spoolss_GetJob(struct pipes_struct *p,
9063                        struct spoolss_GetJob *r)
9064 {
9065         WERROR result = WERR_OK;
9066         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9067         int snum;
9068         int count;
9069         print_queue_struct      *queue = NULL;
9070         print_status_struct prt_status;
9071
9072         /* that's an [in out] buffer */
9073
9074         if (!r->in.buffer && (r->in.offered != 0)) {
9075                 return WERR_INVALID_PARAM;
9076         }
9077
9078         DEBUG(5,("_spoolss_GetJob\n"));
9079
9080         *r->out.needed = 0;
9081
9082         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9083                 return WERR_BADFID;
9084         }
9085
9086         result = winreg_get_printer(p->mem_ctx,
9087                                     get_session_info_system(),
9088                                     p->msg_ctx,
9089                                     lp_const_servicename(snum),
9090                                     &pinfo2);
9091         if (!W_ERROR_IS_OK(result)) {
9092                 return result;
9093         }
9094
9095         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9096
9097         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9098                      count, prt_status.status, prt_status.message));
9099
9100         switch (r->in.level) {
9101         case 1:
9102                 result = getjob_level_1(p->mem_ctx,
9103                                         queue, count, snum, pinfo2,
9104                                         r->in.job_id, &r->out.info->info1);
9105                 break;
9106         case 2:
9107                 result = getjob_level_2(p->mem_ctx,
9108                                         queue, count, snum, pinfo2,
9109                                         r->in.job_id, &r->out.info->info2);
9110                 break;
9111         default:
9112                 result = WERR_UNKNOWN_LEVEL;
9113                 break;
9114         }
9115
9116         SAFE_FREE(queue);
9117         TALLOC_FREE(pinfo2);
9118
9119         if (!W_ERROR_IS_OK(result)) {
9120                 TALLOC_FREE(r->out.info);
9121                 return result;
9122         }
9123
9124         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9125                                                                                    r->in.level);
9126         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9127
9128         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9129 }
9130
9131 /****************************************************************
9132  _spoolss_GetPrinterDataEx
9133 ****************************************************************/
9134
9135 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9136                                  struct spoolss_GetPrinterDataEx *r)
9137 {
9138
9139         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9140         const char *printer;
9141         int                     snum = 0;
9142         WERROR result = WERR_OK;
9143         DATA_BLOB blob;
9144         enum winreg_Type val_type;
9145         uint8_t *val_data;
9146         uint32_t val_size;
9147
9148
9149         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9150
9151         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9152                 r->in.key_name, r->in.value_name));
9153
9154         /* in case of problem, return some default values */
9155
9156         *r->out.needed  = 0;
9157         *r->out.type    = REG_NONE;
9158
9159         if (!Printer) {
9160                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9161                         OUR_HANDLE(r->in.handle)));
9162                 result = WERR_BADFID;
9163                 goto done;
9164         }
9165
9166         /* Is the handle to a printer or to the server? */
9167
9168         if (Printer->printer_type == SPLHND_SERVER) {
9169
9170                 union spoolss_PrinterData data;
9171
9172                 result = getprinterdata_printer_server(p->mem_ctx,
9173                                                        r->in.value_name,
9174                                                        r->out.type,
9175                                                        &data);
9176                 if (!W_ERROR_IS_OK(result)) {
9177                         return result;
9178                 }
9179
9180                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9181                                                   *r->out.type, &data);
9182                 if (!W_ERROR_IS_OK(result)) {
9183                         return result;
9184                 }
9185
9186                 *r->out.needed = blob.length;
9187
9188                 if (r->in.offered >= *r->out.needed) {
9189                         memcpy(r->out.data, blob.data, blob.length);
9190                 }
9191
9192                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9193         }
9194
9195         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9196                 return WERR_BADFID;
9197         }
9198         printer = lp_const_servicename(snum);
9199
9200         /* check to see if the keyname is valid */
9201         if (!strlen(r->in.key_name)) {
9202                 return WERR_INVALID_PARAM;
9203         }
9204
9205         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9206         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9207             strequal(r->in.value_name, "ChangeId")) {
9208                 *r->out.type = REG_DWORD;
9209                 *r->out.needed = 4;
9210                 if (r->in.offered >= *r->out.needed) {
9211                         uint32_t changeid = 0;
9212
9213                         result = winreg_printer_get_changeid(p->mem_ctx,
9214                                                              get_session_info_system(),
9215                                                              p->msg_ctx,
9216                                                              printer,
9217                                                              &changeid);
9218                         if (!W_ERROR_IS_OK(result)) {
9219                                 return result;
9220                         }
9221
9222                         SIVAL(r->out.data, 0, changeid);
9223                         result = WERR_OK;
9224                 }
9225                 goto done;
9226         }
9227
9228         result = winreg_get_printer_dataex(p->mem_ctx,
9229                                            get_session_info_system(),
9230                                            p->msg_ctx,
9231                                            printer,
9232                                            r->in.key_name,
9233                                            r->in.value_name,
9234                                            &val_type,
9235                                            &val_data,
9236                                            &val_size);
9237         if (!W_ERROR_IS_OK(result)) {
9238                 return result;
9239         }
9240
9241         *r->out.needed = val_size;
9242         *r->out.type = val_type;
9243
9244         if (r->in.offered >= *r->out.needed) {
9245                 memcpy(r->out.data, val_data, val_size);
9246         }
9247
9248  done:
9249         /* retain type when returning WERR_MORE_DATA */
9250         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9251
9252         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9253 }
9254
9255 /****************************************************************
9256  _spoolss_SetPrinterDataEx
9257 ****************************************************************/
9258
9259 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9260                                  struct spoolss_SetPrinterDataEx *r)
9261 {
9262         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9263         int                     snum = 0;
9264         WERROR                  result = WERR_OK;
9265         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9266         char                    *oid_string;
9267
9268         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9269
9270         /* From MSDN documentation of SetPrinterDataEx: pass request to
9271            SetPrinterData if key is "PrinterDriverData" */
9272
9273         if (!Printer) {
9274                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9275                         OUR_HANDLE(r->in.handle)));
9276                 return WERR_BADFID;
9277         }
9278
9279         if (Printer->printer_type == SPLHND_SERVER) {
9280                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9281                         "Not implemented for server handles yet\n"));
9282                 return WERR_INVALID_PARAM;
9283         }
9284
9285         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9286                 return WERR_BADFID;
9287         }
9288
9289         /*
9290          * Access check : NT returns "access denied" if you make a
9291          * SetPrinterData call without the necessary privildge.
9292          * we were originally returning OK if nothing changed
9293          * which made Win2k issue **a lot** of SetPrinterData
9294          * when connecting to a printer  --jerry
9295          */
9296
9297         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9298                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9299                         "change denied by handle access permissions\n"));
9300                 return WERR_ACCESS_DENIED;
9301         }
9302
9303         result = winreg_get_printer(Printer,
9304                                     get_session_info_system(),
9305                                     p->msg_ctx,
9306                                     lp_servicename(snum),
9307                                     &pinfo2);
9308         if (!W_ERROR_IS_OK(result)) {
9309                 return result;
9310         }
9311
9312         /* check for OID in valuename */
9313
9314         oid_string = strchr(r->in.value_name, ',');
9315         if (oid_string) {
9316                 *oid_string = '\0';
9317                 oid_string++;
9318         }
9319
9320         /* save the registry data */
9321
9322         result = winreg_set_printer_dataex(p->mem_ctx,
9323                                            get_session_info_system(),
9324                                            p->msg_ctx,
9325                                            pinfo2->sharename,
9326                                            r->in.key_name,
9327                                            r->in.value_name,
9328                                            r->in.type,
9329                                            r->in.data,
9330                                            r->in.offered);
9331
9332         if (W_ERROR_IS_OK(result)) {
9333                 /* save the OID if one was specified */
9334                 if (oid_string) {
9335                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9336                                 r->in.key_name, SPOOL_OID_KEY);
9337                         if (!str) {
9338                                 result = WERR_NOMEM;
9339                                 goto done;
9340                         }
9341
9342                         /*
9343                          * I'm not checking the status here on purpose.  Don't know
9344                          * if this is right, but I'm returning the status from the
9345                          * previous set_printer_dataex() call.  I have no idea if
9346                          * this is right.    --jerry
9347                          */
9348                         winreg_set_printer_dataex(p->mem_ctx,
9349                                                   get_session_info_system(),
9350                                                   p->msg_ctx,
9351                                                   pinfo2->sharename,
9352                                                   str,
9353                                                   r->in.value_name,
9354                                                   REG_SZ,
9355                                                   (uint8_t *) oid_string,
9356                                                   strlen(oid_string) + 1);
9357                 }
9358
9359                 result = winreg_printer_update_changeid(p->mem_ctx,
9360                                                         get_session_info_system(),
9361                                                         p->msg_ctx,
9362                                                         lp_const_servicename(snum));
9363
9364         }
9365
9366 done:
9367         talloc_free(pinfo2);
9368         return result;
9369 }
9370
9371 /****************************************************************
9372  _spoolss_DeletePrinterDataEx
9373 ****************************************************************/
9374
9375 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9376                                     struct spoolss_DeletePrinterDataEx *r)
9377 {
9378         const char *printer;
9379         int             snum=0;
9380         WERROR          status = WERR_OK;
9381         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9382
9383         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9384
9385         if (!Printer) {
9386                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9387                         "Invalid handle (%s:%u:%u).\n",
9388                         OUR_HANDLE(r->in.handle)));
9389                 return WERR_BADFID;
9390         }
9391
9392         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9393                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9394                         "printer properties change denied by handle\n"));
9395                 return WERR_ACCESS_DENIED;
9396         }
9397
9398         if (!r->in.value_name || !r->in.key_name) {
9399                 return WERR_NOMEM;
9400         }
9401
9402         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9403                 return WERR_BADFID;
9404         }
9405         printer = lp_const_servicename(snum);
9406
9407         status = winreg_delete_printer_dataex(p->mem_ctx,
9408                                               get_session_info_system(),
9409                                               p->msg_ctx,
9410                                               printer,
9411                                               r->in.key_name,
9412                                               r->in.value_name);
9413         if (W_ERROR_IS_OK(status)) {
9414                 status = winreg_printer_update_changeid(p->mem_ctx,
9415                                                         get_session_info_system(),
9416                                                         p->msg_ctx,
9417                                                         printer);
9418         }
9419
9420         return status;
9421 }
9422
9423 /****************************************************************
9424  _spoolss_EnumPrinterKey
9425 ****************************************************************/
9426
9427 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9428                                struct spoolss_EnumPrinterKey *r)
9429 {
9430         uint32_t        num_keys;
9431         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9432         int             snum = 0;
9433         WERROR          result = WERR_BADFILE;
9434         const char **array = NULL;
9435         DATA_BLOB blob;
9436
9437         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9438
9439         if (!Printer) {
9440                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9441                         OUR_HANDLE(r->in.handle)));
9442                 return WERR_BADFID;
9443         }
9444
9445         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9446                 return WERR_BADFID;
9447         }
9448
9449         result = winreg_enum_printer_key(p->mem_ctx,
9450                                          get_session_info_system(),
9451                                          p->msg_ctx,
9452                                          lp_const_servicename(snum),
9453                                          r->in.key_name,
9454                                          &num_keys,
9455                                          &array);
9456         if (!W_ERROR_IS_OK(result)) {
9457                 goto done;
9458         }
9459
9460         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9461                 result = WERR_NOMEM;
9462                 goto done;
9463         }
9464
9465         *r->out._ndr_size = r->in.offered / 2;
9466         *r->out.needed = blob.length;
9467
9468         if (r->in.offered < *r->out.needed) {
9469                 result = WERR_MORE_DATA;
9470         } else {
9471                 result = WERR_OK;
9472                 r->out.key_buffer->string_array = array;
9473         }
9474
9475  done:
9476         if (!W_ERROR_IS_OK(result)) {
9477                 TALLOC_FREE(array);
9478                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9479                         *r->out.needed = 0;
9480                 }
9481         }
9482
9483         return result;
9484 }
9485
9486 /****************************************************************
9487  _spoolss_DeletePrinterKey
9488 ****************************************************************/
9489
9490 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9491                                  struct spoolss_DeletePrinterKey *r)
9492 {
9493         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9494         int                     snum=0;
9495         WERROR                  status;
9496         const char *printer;
9497
9498         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9499
9500         if (!Printer) {
9501                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9502                         OUR_HANDLE(r->in.handle)));
9503                 return WERR_BADFID;
9504         }
9505
9506         /* if keyname == NULL, return error */
9507         if ( !r->in.key_name )
9508                 return WERR_INVALID_PARAM;
9509
9510         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9511                 return WERR_BADFID;
9512         }
9513
9514         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9515                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9516                         "printer properties change denied by handle\n"));
9517                 return WERR_ACCESS_DENIED;
9518         }
9519
9520         printer = lp_const_servicename(snum);
9521
9522         /* delete the key and all subkeys */
9523         status = winreg_delete_printer_key(p->mem_ctx,
9524                                            get_session_info_system(),
9525                                            p->msg_ctx,
9526                                            printer,
9527                                            r->in.key_name);
9528         if (W_ERROR_IS_OK(status)) {
9529                 status = winreg_printer_update_changeid(p->mem_ctx,
9530                                                         get_session_info_system(),
9531                                                         p->msg_ctx,
9532                                                         printer);
9533         }
9534
9535         return status;
9536 }
9537
9538 /****************************************************************
9539  _spoolss_EnumPrinterDataEx
9540 ****************************************************************/
9541
9542 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9543                                   struct spoolss_EnumPrinterDataEx *r)
9544 {
9545         uint32_t        count = 0;
9546         struct spoolss_PrinterEnumValues *info = NULL;
9547         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9548         int             snum;
9549         WERROR          result;
9550
9551         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9552
9553         *r->out.count = 0;
9554         *r->out.needed = 0;
9555         *r->out.info = NULL;
9556
9557         if (!Printer) {
9558                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9559                         OUR_HANDLE(r->in.handle)));
9560                 return WERR_BADFID;
9561         }
9562
9563         /*
9564          * first check for a keyname of NULL or "".  Win2k seems to send
9565          * this a lot and we should send back WERR_INVALID_PARAM
9566          * no need to spend time looking up the printer in this case.
9567          * --jerry
9568          */
9569
9570         if (!strlen(r->in.key_name)) {
9571                 result = WERR_INVALID_PARAM;
9572                 goto done;
9573         }
9574
9575         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9576                 return WERR_BADFID;
9577         }
9578
9579         /* now look for a match on the key name */
9580         result = winreg_enum_printer_dataex(p->mem_ctx,
9581                                             get_session_info_system(),
9582                                             p->msg_ctx,
9583                                             lp_const_servicename(snum),
9584                                             r->in.key_name,
9585                                             &count,
9586                                             &info);
9587         if (!W_ERROR_IS_OK(result)) {
9588                 goto done;
9589         }
9590
9591 #if 0 /* FIXME - gd */
9592         /* housekeeping information in the reply */
9593
9594         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9595          * the hand marshalled container size is a multiple
9596          * of 4 bytes for RPC alignment.
9597          */
9598
9599         if (needed % 4) {
9600                 needed += 4-(needed % 4);
9601         }
9602 #endif
9603         *r->out.count   = count;
9604         *r->out.info    = info;
9605
9606  done:
9607         if (!W_ERROR_IS_OK(result)) {
9608                 return result;
9609         }
9610
9611         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9612                                                spoolss_EnumPrinterDataEx,
9613                                                *r->out.info,
9614                                                *r->out.count);
9615         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9616         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9617
9618         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9619 }
9620
9621 /****************************************************************************
9622 ****************************************************************************/
9623
9624 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9625                                                  const char *servername,
9626                                                  const char *environment,
9627                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9628 {
9629         WERROR werr;
9630         char *path = NULL;
9631
9632         werr = compose_spoolss_server_path(mem_ctx,
9633                                            servername,
9634                                            environment,
9635                                            SPOOLSS_PRTPROCS_PATH,
9636                                            &path);
9637         if (!W_ERROR_IS_OK(werr)) {
9638                 return werr;
9639         }
9640
9641         DEBUG(4,("print processor directory: [%s]\n", path));
9642
9643         r->directory_name = path;
9644
9645         return WERR_OK;
9646 }
9647
9648 /****************************************************************
9649  _spoolss_GetPrintProcessorDirectory
9650 ****************************************************************/
9651
9652 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9653                                            struct spoolss_GetPrintProcessorDirectory *r)
9654 {
9655         WERROR result;
9656         char *prnproc_share = NULL;
9657         bool prnproc_share_exists = false;
9658         int snum;
9659
9660         /* that's an [in out] buffer */
9661
9662         if (!r->in.buffer && (r->in.offered != 0)) {
9663                 return WERR_INVALID_PARAM;
9664         }
9665
9666         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9667                 r->in.level));
9668
9669         *r->out.needed = 0;
9670
9671         /* r->in.level is ignored */
9672
9673         /* We always should reply with a local print processor directory so that
9674          * users are not forced to have a [prnproc$] share on the Samba spoolss
9675          * server, if users decide to do so, lets announce it though - Guenther */
9676
9677         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9678         if (!prnproc_share) {
9679                 return WERR_NOMEM;
9680         }
9681         if (snum != -1) {
9682                 prnproc_share_exists = true;
9683         }
9684
9685         result = getprintprocessordirectory_level_1(p->mem_ctx,
9686                                                     prnproc_share_exists ? r->in.server : NULL,
9687                                                     r->in.environment,
9688                                                     &r->out.info->info1);
9689         if (!W_ERROR_IS_OK(result)) {
9690                 TALLOC_FREE(r->out.info);
9691                 return result;
9692         }
9693
9694         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9695                                                                                    r->out.info, r->in.level);
9696         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9697
9698         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9699 }
9700
9701 /*******************************************************************
9702  ********************************************************************/
9703
9704 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9705                                const char *dllname)
9706 {
9707         enum ndr_err_code ndr_err;
9708         struct spoolss_MonitorUi ui;
9709
9710         ui.dll_name = dllname;
9711
9712         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9713                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9714         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9715                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9716         }
9717         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9718 }
9719
9720 /*******************************************************************
9721  Streams the monitor UI DLL name in UNICODE
9722 *******************************************************************/
9723
9724 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9725                                struct security_token *token, DATA_BLOB *in,
9726                                DATA_BLOB *out, uint32_t *needed)
9727 {
9728         const char *dllname = "tcpmonui.dll";
9729
9730         *needed = (strlen(dllname)+1) * 2;
9731
9732         if (out->length < *needed) {
9733                 return WERR_INSUFFICIENT_BUFFER;
9734         }
9735
9736         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9737                 return WERR_NOMEM;
9738         }
9739
9740         return WERR_OK;
9741 }
9742
9743 /*******************************************************************
9744  ********************************************************************/
9745
9746 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9747                              struct spoolss_PortData1 *port1,
9748                              const DATA_BLOB *buf)
9749 {
9750         enum ndr_err_code ndr_err;
9751         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9752                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9753         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9754                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9755         }
9756         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9757 }
9758
9759 /*******************************************************************
9760  ********************************************************************/
9761
9762 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9763                              struct spoolss_PortData2 *port2,
9764                              const DATA_BLOB *buf)
9765 {
9766         enum ndr_err_code ndr_err;
9767         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9768                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9769         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9770                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9771         }
9772         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9773 }
9774
9775 /*******************************************************************
9776  Create a new TCP/IP port
9777 *******************************************************************/
9778
9779 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9780                              struct security_token *token, DATA_BLOB *in,
9781                              DATA_BLOB *out, uint32_t *needed)
9782 {
9783         struct spoolss_PortData1 port1;
9784         struct spoolss_PortData2 port2;
9785         char *device_uri = NULL;
9786         uint32_t version;
9787
9788         const char *portname;
9789         const char *hostaddress;
9790         const char *queue;
9791         uint32_t port_number;
9792         uint32_t protocol;
9793
9794         /* peek for spoolss_PortData version */
9795
9796         if (!in || (in->length < (128 + 4))) {
9797                 return WERR_GENERAL_FAILURE;
9798         }
9799
9800         version = IVAL(in->data, 128);
9801
9802         switch (version) {
9803                 case 1:
9804                         ZERO_STRUCT(port1);
9805
9806                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9807                                 return WERR_NOMEM;
9808                         }
9809
9810                         portname        = port1.portname;
9811                         hostaddress     = port1.hostaddress;
9812                         queue           = port1.queue;
9813                         protocol        = port1.protocol;
9814                         port_number     = port1.port_number;
9815
9816                         break;
9817                 case 2:
9818                         ZERO_STRUCT(port2);
9819
9820                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9821                                 return WERR_NOMEM;
9822                         }
9823
9824                         portname        = port2.portname;
9825                         hostaddress     = port2.hostaddress;
9826                         queue           = port2.queue;
9827                         protocol        = port2.protocol;
9828                         port_number     = port2.port_number;
9829
9830                         break;
9831                 default:
9832                         DEBUG(1,("xcvtcp_addport: "
9833                                 "unknown version of port_data: %d\n", version));
9834                         return WERR_UNKNOWN_PORT;
9835         }
9836
9837         /* create the device URI and call the add_port_hook() */
9838
9839         switch (protocol) {
9840         case PROTOCOL_RAWTCP_TYPE:
9841                 device_uri = talloc_asprintf(mem_ctx,
9842                                 "socket://%s:%d/", hostaddress,
9843                                 port_number);
9844                 break;
9845
9846         case PROTOCOL_LPR_TYPE:
9847                 device_uri = talloc_asprintf(mem_ctx,
9848                         "lpr://%s/%s", hostaddress, queue );
9849                 break;
9850
9851         default:
9852                 return WERR_UNKNOWN_PORT;
9853         }
9854
9855         if (!device_uri) {
9856                 return WERR_NOMEM;
9857         }
9858
9859         return add_port_hook(mem_ctx, token, portname, device_uri);
9860 }
9861
9862 /*******************************************************************
9863 *******************************************************************/
9864
9865 struct xcv_api_table xcvtcp_cmds[] = {
9866         { "MonitorUI",  xcvtcp_monitorui },
9867         { "AddPort",    xcvtcp_addport},
9868         { NULL,         NULL }
9869 };
9870
9871 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9872                                      struct security_token *token, const char *command,
9873                                      DATA_BLOB *inbuf,
9874                                      DATA_BLOB *outbuf,
9875                                      uint32_t *needed )
9876 {
9877         int i;
9878
9879         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9880
9881         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9882                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9883                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9884         }
9885
9886         return WERR_BADFUNC;
9887 }
9888
9889 /*******************************************************************
9890 *******************************************************************/
9891 #if 0   /* don't support management using the "Local Port" monitor */
9892
9893 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9894                                  struct security_token *token, DATA_BLOB *in,
9895                                  DATA_BLOB *out, uint32_t *needed)
9896 {
9897         const char *dllname = "localui.dll";
9898
9899         *needed = (strlen(dllname)+1) * 2;
9900
9901         if (out->length < *needed) {
9902                 return WERR_INSUFFICIENT_BUFFER;
9903         }
9904
9905         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9906                 return WERR_NOMEM;
9907         }
9908
9909         return WERR_OK;
9910 }
9911
9912 /*******************************************************************
9913 *******************************************************************/
9914
9915 struct xcv_api_table xcvlocal_cmds[] = {
9916         { "MonitorUI",  xcvlocal_monitorui },
9917         { NULL,         NULL }
9918 };
9919 #else
9920 struct xcv_api_table xcvlocal_cmds[] = {
9921         { NULL,         NULL }
9922 };
9923 #endif
9924
9925
9926
9927 /*******************************************************************
9928 *******************************************************************/
9929
9930 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9931                                        struct security_token *token, const char *command,
9932                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9933                                        uint32_t *needed)
9934 {
9935         int i;
9936
9937         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9938
9939         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9940                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9941                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9942         }
9943         return WERR_BADFUNC;
9944 }
9945
9946 /****************************************************************
9947  _spoolss_XcvData
9948 ****************************************************************/
9949
9950 WERROR _spoolss_XcvData(struct pipes_struct *p,
9951                         struct spoolss_XcvData *r)
9952 {
9953         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9954         DATA_BLOB out_data = data_blob_null;
9955         WERROR werror;
9956
9957         if (!Printer) {
9958                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9959                         OUR_HANDLE(r->in.handle)));
9960                 return WERR_BADFID;
9961         }
9962
9963         /* Has to be a handle to the TCP/IP port monitor */
9964
9965         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9966                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9967                 return WERR_BADFID;
9968         }
9969
9970         /* requires administrative access to the server */
9971
9972         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9973                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9974                 return WERR_ACCESS_DENIED;
9975         }
9976
9977         /* Allocate the outgoing buffer */
9978
9979         if (r->in.out_data_size) {
9980                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9981                 if (out_data.data == NULL) {
9982                         return WERR_NOMEM;
9983                 }
9984         }
9985
9986         switch ( Printer->printer_type ) {
9987         case SPLHND_PORTMON_TCP:
9988                 werror = process_xcvtcp_command(p->mem_ctx,
9989                                                 p->session_info->security_token,
9990                                                 r->in.function_name,
9991                                                 &r->in.in_data, &out_data,
9992                                                 r->out.needed);
9993                 break;
9994         case SPLHND_PORTMON_LOCAL:
9995                 werror = process_xcvlocal_command(p->mem_ctx,
9996                                                   p->session_info->security_token,
9997                                                   r->in.function_name,
9998                                                   &r->in.in_data, &out_data,
9999                                                   r->out.needed);
10000                 break;
10001         default:
10002                 werror = WERR_INVALID_PRINT_MONITOR;
10003         }
10004
10005         if (!W_ERROR_IS_OK(werror)) {
10006                 return werror;
10007         }
10008
10009         *r->out.status_code = 0;
10010
10011         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10012                 memcpy(r->out.out_data, out_data.data,
10013                         MIN(r->in.out_data_size, out_data.length));
10014         }
10015
10016         return WERR_OK;
10017 }
10018
10019 /****************************************************************
10020  _spoolss_AddPrintProcessor
10021 ****************************************************************/
10022
10023 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10024                                   struct spoolss_AddPrintProcessor *r)
10025 {
10026         /* for now, just indicate success and ignore the add.  We'll
10027            automatically set the winprint processor for printer
10028            entries later.  Used to debug the LexMark Optra S 1855 PCL
10029            driver --jerry */
10030
10031         return WERR_OK;
10032 }
10033
10034 /****************************************************************
10035  _spoolss_AddPort
10036 ****************************************************************/
10037
10038 WERROR _spoolss_AddPort(struct pipes_struct *p,
10039                         struct spoolss_AddPort *r)
10040 {
10041         /* do what w2k3 does */
10042
10043         return WERR_NOT_SUPPORTED;
10044 }
10045
10046 /****************************************************************
10047  _spoolss_GetPrinterDriver
10048 ****************************************************************/
10049
10050 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10051                                  struct spoolss_GetPrinterDriver *r)
10052 {
10053         p->rng_fault_state = true;
10054         return WERR_NOT_SUPPORTED;
10055 }
10056
10057 /****************************************************************
10058  _spoolss_ReadPrinter
10059 ****************************************************************/
10060
10061 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10062                             struct spoolss_ReadPrinter *r)
10063 {
10064         p->rng_fault_state = true;
10065         return WERR_NOT_SUPPORTED;
10066 }
10067
10068 /****************************************************************
10069  _spoolss_WaitForPrinterChange
10070 ****************************************************************/
10071
10072 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10073                                      struct spoolss_WaitForPrinterChange *r)
10074 {
10075         p->rng_fault_state = true;
10076         return WERR_NOT_SUPPORTED;
10077 }
10078
10079 /****************************************************************
10080  _spoolss_ConfigurePort
10081 ****************************************************************/
10082
10083 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10084                               struct spoolss_ConfigurePort *r)
10085 {
10086         p->rng_fault_state = true;
10087         return WERR_NOT_SUPPORTED;
10088 }
10089
10090 /****************************************************************
10091  _spoolss_DeletePort
10092 ****************************************************************/
10093
10094 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10095                            struct spoolss_DeletePort *r)
10096 {
10097         p->rng_fault_state = true;
10098         return WERR_NOT_SUPPORTED;
10099 }
10100
10101 /****************************************************************
10102  _spoolss_CreatePrinterIC
10103 ****************************************************************/
10104
10105 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10106                                 struct spoolss_CreatePrinterIC *r)
10107 {
10108         p->rng_fault_state = true;
10109         return WERR_NOT_SUPPORTED;
10110 }
10111
10112 /****************************************************************
10113  _spoolss_PlayGDIScriptOnPrinterIC
10114 ****************************************************************/
10115
10116 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10117                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10118 {
10119         p->rng_fault_state = true;
10120         return WERR_NOT_SUPPORTED;
10121 }
10122
10123 /****************************************************************
10124  _spoolss_DeletePrinterIC
10125 ****************************************************************/
10126
10127 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10128                                 struct spoolss_DeletePrinterIC *r)
10129 {
10130         p->rng_fault_state = true;
10131         return WERR_NOT_SUPPORTED;
10132 }
10133
10134 /****************************************************************
10135  _spoolss_AddPrinterConnection
10136 ****************************************************************/
10137
10138 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10139                                      struct spoolss_AddPrinterConnection *r)
10140 {
10141         p->rng_fault_state = true;
10142         return WERR_NOT_SUPPORTED;
10143 }
10144
10145 /****************************************************************
10146  _spoolss_DeletePrinterConnection
10147 ****************************************************************/
10148
10149 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10150                                         struct spoolss_DeletePrinterConnection *r)
10151 {
10152         p->rng_fault_state = true;
10153         return WERR_NOT_SUPPORTED;
10154 }
10155
10156 /****************************************************************
10157  _spoolss_PrinterMessageBox
10158 ****************************************************************/
10159
10160 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10161                                   struct spoolss_PrinterMessageBox *r)
10162 {
10163         p->rng_fault_state = true;
10164         return WERR_NOT_SUPPORTED;
10165 }
10166
10167 /****************************************************************
10168  _spoolss_AddMonitor
10169 ****************************************************************/
10170
10171 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10172                            struct spoolss_AddMonitor *r)
10173 {
10174         p->rng_fault_state = true;
10175         return WERR_NOT_SUPPORTED;
10176 }
10177
10178 /****************************************************************
10179  _spoolss_DeleteMonitor
10180 ****************************************************************/
10181
10182 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10183                               struct spoolss_DeleteMonitor *r)
10184 {
10185         p->rng_fault_state = true;
10186         return WERR_NOT_SUPPORTED;
10187 }
10188
10189 /****************************************************************
10190  _spoolss_DeletePrintProcessor
10191 ****************************************************************/
10192
10193 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10194                                      struct spoolss_DeletePrintProcessor *r)
10195 {
10196         p->rng_fault_state = true;
10197         return WERR_NOT_SUPPORTED;
10198 }
10199
10200 /****************************************************************
10201  _spoolss_AddPrintProvidor
10202 ****************************************************************/
10203
10204 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10205                                  struct spoolss_AddPrintProvidor *r)
10206 {
10207         p->rng_fault_state = true;
10208         return WERR_NOT_SUPPORTED;
10209 }
10210
10211 /****************************************************************
10212  _spoolss_DeletePrintProvidor
10213 ****************************************************************/
10214
10215 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10216                                     struct spoolss_DeletePrintProvidor *r)
10217 {
10218         p->rng_fault_state = true;
10219         return WERR_NOT_SUPPORTED;
10220 }
10221
10222 /****************************************************************
10223  _spoolss_FindFirstPrinterChangeNotification
10224 ****************************************************************/
10225
10226 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10227                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10228 {
10229         p->rng_fault_state = true;
10230         return WERR_NOT_SUPPORTED;
10231 }
10232
10233 /****************************************************************
10234  _spoolss_FindNextPrinterChangeNotification
10235 ****************************************************************/
10236
10237 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10238                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10239 {
10240         p->rng_fault_state = true;
10241         return WERR_NOT_SUPPORTED;
10242 }
10243
10244 /****************************************************************
10245  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10246 ****************************************************************/
10247
10248 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10249                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10250 {
10251         p->rng_fault_state = true;
10252         return WERR_NOT_SUPPORTED;
10253 }
10254
10255 /****************************************************************
10256  _spoolss_ReplyOpenPrinter
10257 ****************************************************************/
10258
10259 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10260                                  struct spoolss_ReplyOpenPrinter *r)
10261 {
10262         p->rng_fault_state = true;
10263         return WERR_NOT_SUPPORTED;
10264 }
10265
10266 /****************************************************************
10267  _spoolss_RouterReplyPrinter
10268 ****************************************************************/
10269
10270 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10271                                    struct spoolss_RouterReplyPrinter *r)
10272 {
10273         p->rng_fault_state = true;
10274         return WERR_NOT_SUPPORTED;
10275 }
10276
10277 /****************************************************************
10278  _spoolss_ReplyClosePrinter
10279 ****************************************************************/
10280
10281 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10282                                   struct spoolss_ReplyClosePrinter *r)
10283 {
10284         p->rng_fault_state = true;
10285         return WERR_NOT_SUPPORTED;
10286 }
10287
10288 /****************************************************************
10289  _spoolss_AddPortEx
10290 ****************************************************************/
10291
10292 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10293                           struct spoolss_AddPortEx *r)
10294 {
10295         p->rng_fault_state = true;
10296         return WERR_NOT_SUPPORTED;
10297 }
10298
10299 /****************************************************************
10300  _spoolss_RouterFindFirstPrinterChangeNotification
10301 ****************************************************************/
10302
10303 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10304                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10305 {
10306         p->rng_fault_state = true;
10307         return WERR_NOT_SUPPORTED;
10308 }
10309
10310 /****************************************************************
10311  _spoolss_SpoolerInit
10312 ****************************************************************/
10313
10314 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10315                             struct spoolss_SpoolerInit *r)
10316 {
10317         p->rng_fault_state = true;
10318         return WERR_NOT_SUPPORTED;
10319 }
10320
10321 /****************************************************************
10322  _spoolss_ResetPrinterEx
10323 ****************************************************************/
10324
10325 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10326                                struct spoolss_ResetPrinterEx *r)
10327 {
10328         p->rng_fault_state = true;
10329         return WERR_NOT_SUPPORTED;
10330 }
10331
10332 /****************************************************************
10333  _spoolss_RouterReplyPrinterEx
10334 ****************************************************************/
10335
10336 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10337                                      struct spoolss_RouterReplyPrinterEx *r)
10338 {
10339         p->rng_fault_state = true;
10340         return WERR_NOT_SUPPORTED;
10341 }
10342
10343 /****************************************************************
10344  _spoolss_44
10345 ****************************************************************/
10346
10347 WERROR _spoolss_44(struct pipes_struct *p,
10348                    struct spoolss_44 *r)
10349 {
10350         p->rng_fault_state = true;
10351         return WERR_NOT_SUPPORTED;
10352 }
10353
10354 /****************************************************************
10355  _spoolss_SetPort
10356 ****************************************************************/
10357
10358 WERROR _spoolss_SetPort(struct pipes_struct *p,
10359                         struct spoolss_SetPort *r)
10360 {
10361         p->rng_fault_state = true;
10362         return WERR_NOT_SUPPORTED;
10363 }
10364
10365 /****************************************************************
10366  _spoolss_4a
10367 ****************************************************************/
10368
10369 WERROR _spoolss_4a(struct pipes_struct *p,
10370                    struct spoolss_4a *r)
10371 {
10372         p->rng_fault_state = true;
10373         return WERR_NOT_SUPPORTED;
10374 }
10375
10376 /****************************************************************
10377  _spoolss_4b
10378 ****************************************************************/
10379
10380 WERROR _spoolss_4b(struct pipes_struct *p,
10381                    struct spoolss_4b *r)
10382 {
10383         p->rng_fault_state = true;
10384         return WERR_NOT_SUPPORTED;
10385 }
10386
10387 /****************************************************************
10388  _spoolss_4c
10389 ****************************************************************/
10390
10391 WERROR _spoolss_4c(struct pipes_struct *p,
10392                    struct spoolss_4c *r)
10393 {
10394         p->rng_fault_state = true;
10395         return WERR_NOT_SUPPORTED;
10396 }
10397
10398 /****************************************************************
10399  _spoolss_53
10400 ****************************************************************/
10401
10402 WERROR _spoolss_53(struct pipes_struct *p,
10403                    struct spoolss_53 *r)
10404 {
10405         p->rng_fault_state = true;
10406         return WERR_NOT_SUPPORTED;
10407 }
10408
10409 /****************************************************************
10410  _spoolss_AddPerMachineConnection
10411 ****************************************************************/
10412
10413 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10414                                         struct spoolss_AddPerMachineConnection *r)
10415 {
10416         p->rng_fault_state = true;
10417         return WERR_NOT_SUPPORTED;
10418 }
10419
10420 /****************************************************************
10421  _spoolss_DeletePerMachineConnection
10422 ****************************************************************/
10423
10424 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10425                                            struct spoolss_DeletePerMachineConnection *r)
10426 {
10427         p->rng_fault_state = true;
10428         return WERR_NOT_SUPPORTED;
10429 }
10430
10431 /****************************************************************
10432  _spoolss_EnumPerMachineConnections
10433 ****************************************************************/
10434
10435 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10436                                           struct spoolss_EnumPerMachineConnections *r)
10437 {
10438         p->rng_fault_state = true;
10439         return WERR_NOT_SUPPORTED;
10440 }
10441
10442 /****************************************************************
10443  _spoolss_5a
10444 ****************************************************************/
10445
10446 WERROR _spoolss_5a(struct pipes_struct *p,
10447                    struct spoolss_5a *r)
10448 {
10449         p->rng_fault_state = true;
10450         return WERR_NOT_SUPPORTED;
10451 }
10452
10453 /****************************************************************
10454  _spoolss_5b
10455 ****************************************************************/
10456
10457 WERROR _spoolss_5b(struct pipes_struct *p,
10458                    struct spoolss_5b *r)
10459 {
10460         p->rng_fault_state = true;
10461         return WERR_NOT_SUPPORTED;
10462 }
10463
10464 /****************************************************************
10465  _spoolss_5c
10466 ****************************************************************/
10467
10468 WERROR _spoolss_5c(struct pipes_struct *p,
10469                    struct spoolss_5c *r)
10470 {
10471         p->rng_fault_state = true;
10472         return WERR_NOT_SUPPORTED;
10473 }
10474
10475 /****************************************************************
10476  _spoolss_5d
10477 ****************************************************************/
10478
10479 WERROR _spoolss_5d(struct pipes_struct *p,
10480                    struct spoolss_5d *r)
10481 {
10482         p->rng_fault_state = true;
10483         return WERR_NOT_SUPPORTED;
10484 }
10485
10486 /****************************************************************
10487  _spoolss_5e
10488 ****************************************************************/
10489
10490 WERROR _spoolss_5e(struct pipes_struct *p,
10491                    struct spoolss_5e *r)
10492 {
10493         p->rng_fault_state = true;
10494         return WERR_NOT_SUPPORTED;
10495 }
10496
10497 /****************************************************************
10498  _spoolss_5f
10499 ****************************************************************/
10500
10501 WERROR _spoolss_5f(struct pipes_struct *p,
10502                    struct spoolss_5f *r)
10503 {
10504         p->rng_fault_state = true;
10505         return WERR_NOT_SUPPORTED;
10506 }
10507
10508 /****************************************************************
10509  _spoolss_60
10510 ****************************************************************/
10511
10512 WERROR _spoolss_60(struct pipes_struct *p,
10513                    struct spoolss_60 *r)
10514 {
10515         p->rng_fault_state = true;
10516         return WERR_NOT_SUPPORTED;
10517 }
10518
10519 /****************************************************************
10520  _spoolss_61
10521 ****************************************************************/
10522
10523 WERROR _spoolss_61(struct pipes_struct *p,
10524                    struct spoolss_61 *r)
10525 {
10526         p->rng_fault_state = true;
10527         return WERR_NOT_SUPPORTED;
10528 }
10529
10530 /****************************************************************
10531  _spoolss_62
10532 ****************************************************************/
10533
10534 WERROR _spoolss_62(struct pipes_struct *p,
10535                    struct spoolss_62 *r)
10536 {
10537         p->rng_fault_state = true;
10538         return WERR_NOT_SUPPORTED;
10539 }
10540
10541 /****************************************************************
10542  _spoolss_63
10543 ****************************************************************/
10544
10545 WERROR _spoolss_63(struct pipes_struct *p,
10546                    struct spoolss_63 *r)
10547 {
10548         p->rng_fault_state = true;
10549         return WERR_NOT_SUPPORTED;
10550 }
10551
10552 /****************************************************************
10553  _spoolss_64
10554 ****************************************************************/
10555
10556 WERROR _spoolss_64(struct pipes_struct *p,
10557                    struct spoolss_64 *r)
10558 {
10559         p->rng_fault_state = true;
10560         return WERR_NOT_SUPPORTED;
10561 }
10562
10563 /****************************************************************
10564  _spoolss_65
10565 ****************************************************************/
10566
10567 WERROR _spoolss_65(struct pipes_struct *p,
10568                    struct spoolss_65 *r)
10569 {
10570         p->rng_fault_state = true;
10571         return WERR_NOT_SUPPORTED;
10572 }
10573
10574 /****************************************************************
10575  _spoolss_GetCorePrinterDrivers
10576 ****************************************************************/
10577
10578 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10579                                       struct spoolss_GetCorePrinterDrivers *r)
10580 {
10581         p->rng_fault_state = true;
10582         return WERR_NOT_SUPPORTED;
10583 }
10584
10585 /****************************************************************
10586  _spoolss_67
10587 ****************************************************************/
10588
10589 WERROR _spoolss_67(struct pipes_struct *p,
10590                    struct spoolss_67 *r)
10591 {
10592         p->rng_fault_state = true;
10593         return WERR_NOT_SUPPORTED;
10594 }
10595
10596 /****************************************************************
10597  _spoolss_GetPrinterDriverPackagePath
10598 ****************************************************************/
10599
10600 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10601                                             struct spoolss_GetPrinterDriverPackagePath *r)
10602 {
10603         p->rng_fault_state = true;
10604         return WERR_NOT_SUPPORTED;
10605 }
10606
10607 /****************************************************************
10608  _spoolss_69
10609 ****************************************************************/
10610
10611 WERROR _spoolss_69(struct pipes_struct *p,
10612                    struct spoolss_69 *r)
10613 {
10614         p->rng_fault_state = true;
10615         return WERR_NOT_SUPPORTED;
10616 }
10617
10618 /****************************************************************
10619  _spoolss_6a
10620 ****************************************************************/
10621
10622 WERROR _spoolss_6a(struct pipes_struct *p,
10623                    struct spoolss_6a *r)
10624 {
10625         p->rng_fault_state = true;
10626         return WERR_NOT_SUPPORTED;
10627 }
10628
10629 /****************************************************************
10630  _spoolss_6b
10631 ****************************************************************/
10632
10633 WERROR _spoolss_6b(struct pipes_struct *p,
10634                    struct spoolss_6b *r)
10635 {
10636         p->rng_fault_state = true;
10637         return WERR_NOT_SUPPORTED;
10638 }
10639
10640 /****************************************************************
10641  _spoolss_6c
10642 ****************************************************************/
10643
10644 WERROR _spoolss_6c(struct pipes_struct *p,
10645                    struct spoolss_6c *r)
10646 {
10647         p->rng_fault_state = true;
10648         return WERR_NOT_SUPPORTED;
10649 }
10650
10651 /****************************************************************
10652  _spoolss_6d
10653 ****************************************************************/
10654
10655 WERROR _spoolss_6d(struct pipes_struct *p,
10656                    struct spoolss_6d *r)
10657 {
10658         p->rng_fault_state = true;
10659         return WERR_NOT_SUPPORTED;
10660 }