4cc06597b92d92ffa2c84a2f91b644424efd09a1
[ddiss/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "rpc_client/cli_winreg_spoolss.h"
57
58 /* macros stolen from s4 spoolss server */
59 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
60         ((info)?ndr_size_##fn(info, level, 0):0)
61
62 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
63         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
64
65 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
66         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
67
68 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
69
70 #undef DBGC_CLASS
71 #define DBGC_CLASS DBGC_RPC_SRV
72
73 #ifndef MAX_OPEN_PRINTER_EXS
74 #define MAX_OPEN_PRINTER_EXS 50
75 #endif
76
77 struct notify_back_channel;
78
79 /* structure to store the printer handles */
80 /* and a reference to what it's pointing to */
81 /* and the notify info asked about */
82 /* that's the central struct */
83 struct printer_handle {
84         struct printer_handle *prev, *next;
85         bool document_started;
86         bool page_started;
87         uint32 jobid; /* jobid in printing backend */
88         int printer_type;
89         const char *servername;
90         fstring sharename;
91         uint32 type;
92         uint32 access_granted;
93         struct {
94                 uint32 flags;
95                 uint32 options;
96                 fstring localmachine;
97                 uint32 printerlocal;
98                 struct spoolss_NotifyOption *option;
99                 struct policy_handle cli_hnd;
100                 struct notify_back_channel *cli_chan;
101                 uint32 change;
102                 /* are we in a FindNextPrinterChangeNotify() call? */
103                 bool fnpcn;
104                 struct messaging_context *msg_ctx;
105         } notify;
106         struct {
107                 fstring machine;
108                 fstring user;
109         } client;
110
111         /* devmode sent in the OpenPrinter() call */
112         struct spoolss_DeviceMode *devmode;
113
114         /* TODO cache the printer info2 structure */
115         struct spoolss_PrinterInfo2 *info2;
116
117 };
118
119 static struct printer_handle *printers_list;
120
121 struct printer_session_counter {
122         struct printer_session_counter *next;
123         struct printer_session_counter *prev;
124
125         int snum;
126         uint32_t counter;
127 };
128
129 static struct printer_session_counter *counter_list;
130
131 struct notify_back_channel {
132         struct notify_back_channel *prev, *next;
133
134         /* associated client */
135         struct sockaddr_storage client_address;
136
137         /* print notify back-channel pipe handle*/
138         struct rpc_pipe_client *cli_pipe;
139         struct dcerpc_binding_handle *binding_handle;
140         uint32_t active_connections;
141 };
142
143 static struct notify_back_channel *back_channels;
144
145 /* Map generic permissions to printer object specific permissions */
146
147 const struct standard_mapping printer_std_mapping = {
148         PRINTER_READ,
149         PRINTER_WRITE,
150         PRINTER_EXECUTE,
151         PRINTER_ALL_ACCESS
152 };
153
154 /* Map generic permissions to print server object specific permissions */
155
156 const struct standard_mapping printserver_std_mapping = {
157         SERVER_READ,
158         SERVER_WRITE,
159         SERVER_EXECUTE,
160         SERVER_ALL_ACCESS
161 };
162
163 /* API table for Xcv Monitor functions */
164
165 struct xcv_api_table {
166         const char *name;
167         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
168 };
169
170 static void prune_printername_cache(void);
171
172 /********************************************************************
173  * Canonicalize servername.
174  ********************************************************************/
175
176 static const char *canon_servername(const char *servername)
177 {
178         const char *pservername = servername;
179         while (*pservername == '\\') {
180                 pservername++;
181         }
182         return pservername;
183 }
184
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
187 {
188         switch (v) {
189         case LPQ_QUEUED:
190                 return 0;
191         case LPQ_PAUSED:
192                 return JOB_STATUS_PAUSED;
193         case LPQ_SPOOLING:
194                 return JOB_STATUS_SPOOLING;
195         case LPQ_PRINTING:
196                 return JOB_STATUS_PRINTING;
197         case LPQ_ERROR:
198                 return JOB_STATUS_ERROR;
199         case LPQ_DELETING:
200                 return JOB_STATUS_DELETING;
201         case LPQ_OFFLINE:
202                 return JOB_STATUS_OFFLINE;
203         case LPQ_PAPEROUT:
204                 return JOB_STATUS_PAPEROUT;
205         case LPQ_PRINTED:
206                 return JOB_STATUS_PRINTED;
207         case LPQ_DELETED:
208                 return JOB_STATUS_DELETED;
209         case LPQ_BLOCKED:
210                 return JOB_STATUS_BLOCKED_DEVQ;
211         case LPQ_USER_INTERVENTION:
212                 return JOB_STATUS_USER_INTERVENTION;
213         }
214         return 0;
215 }
216
217 static int nt_printq_status(int v)
218 {
219         switch (v) {
220         case LPQ_PAUSED:
221                 return PRINTER_STATUS_PAUSED;
222         case LPQ_QUEUED:
223         case LPQ_SPOOLING:
224         case LPQ_PRINTING:
225                 return 0;
226         }
227         return 0;
228 }
229
230 /***************************************************************************
231  Disconnect from the client
232 ****************************************************************************/
233
234 static void srv_spoolss_replycloseprinter(int snum,
235                                           struct printer_handle *prn_hnd)
236 {
237         WERROR result;
238         NTSTATUS status;
239
240         /*
241          * Tell the specific printing tdb we no longer want messages for this printer
242          * by deregistering our PID.
243          */
244
245         if (!print_notify_deregister_pid(snum)) {
246                 DEBUG(0, ("Failed to register our pid for printer %s\n",
247                           lp_const_servicename(snum)));
248         }
249
250         /* weird if the test succeeds !!! */
251         if (prn_hnd->notify.cli_chan == NULL ||
252             prn_hnd->notify.cli_chan->active_connections == 0) {
253                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
254                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
255                 TALLOC_FREE(prn_hnd->notify.cli_chan);
256                 return;
257         }
258
259         status = dcerpc_spoolss_ReplyClosePrinter(
260                                         prn_hnd->notify.cli_chan->binding_handle,
261                                         talloc_tos(),
262                                         &prn_hnd->notify.cli_hnd,
263                                         &result);
264         if (!NT_STATUS_IS_OK(status)) {
265                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
266                           nt_errstr(status)));
267                 result = ntstatus_to_werror(status);
268         } else if (!W_ERROR_IS_OK(result)) {
269                 DEBUG(0, ("reply_close_printer failed [%s].\n",
270                           win_errstr(result)));
271         }
272
273         /* if it's the last connection, deconnect the IPC$ share */
274         if (prn_hnd->notify.cli_chan->active_connections == 1) {
275
276                 prn_hnd->notify.cli_chan->binding_handle = NULL;
277                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
278                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
279                 TALLOC_FREE(prn_hnd->notify.cli_chan);
280
281                 if (prn_hnd->notify.msg_ctx != NULL) {
282                         messaging_deregister(prn_hnd->notify.msg_ctx,
283                                              MSG_PRINTER_NOTIFY2, NULL);
284
285                         /*
286                          * Tell the serverid.tdb we're no longer
287                          * interested in printer notify messages.
288                          */
289
290                         serverid_register_msg_flags(
291                                 messaging_server_id(prn_hnd->notify.msg_ctx),
292                                 false, FLAG_MSG_PRINT_NOTIFY);
293                 }
294         }
295
296         if (prn_hnd->notify.cli_chan) {
297                 prn_hnd->notify.cli_chan->active_connections--;
298                 prn_hnd->notify.cli_chan = NULL;
299         }
300 }
301
302 /****************************************************************************
303  Functions to free a printer entry datastruct.
304 ****************************************************************************/
305
306 static int printer_entry_destructor(struct printer_handle *Printer)
307 {
308         if (Printer->notify.cli_chan != NULL &&
309             Printer->notify.cli_chan->active_connections > 0) {
310                 int snum = -1;
311
312                 switch(Printer->printer_type) {
313                 case SPLHND_SERVER:
314                         srv_spoolss_replycloseprinter(snum, Printer);
315                         break;
316
317                 case SPLHND_PRINTER:
318                         snum = print_queue_snum(Printer->sharename);
319                         if (snum != -1) {
320                                 srv_spoolss_replycloseprinter(snum, Printer);
321                         }
322                         break;
323                 default:
324                         break;
325                 }
326         }
327
328         Printer->notify.flags=0;
329         Printer->notify.options=0;
330         Printer->notify.localmachine[0]='\0';
331         Printer->notify.printerlocal=0;
332         TALLOC_FREE(Printer->notify.option);
333         TALLOC_FREE(Printer->devmode);
334
335         /* Remove from the internal list. */
336         DLIST_REMOVE(printers_list, Printer);
337         return 0;
338 }
339
340 /****************************************************************************
341   find printer index by handle
342 ****************************************************************************/
343
344 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
345                                                         struct policy_handle *hnd)
346 {
347         struct printer_handle *find_printer = NULL;
348
349         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
350                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
351                 return NULL;
352         }
353
354         return find_printer;
355 }
356
357 /****************************************************************************
358  Close printer index by handle.
359 ****************************************************************************/
360
361 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
362 {
363         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
364
365         if (!Printer) {
366                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
367                         OUR_HANDLE(hnd)));
368                 return false;
369         }
370
371         close_policy_hnd(p, hnd);
372
373         return true;
374 }
375
376 /****************************************************************************
377  Delete a printer given a handle.
378 ****************************************************************************/
379
380 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
381                                   const char *sharename,
382                                   struct messaging_context *msg_ctx)
383 {
384         char *cmd = lp_deleteprinter_cmd();
385         char *command = NULL;
386         int ret;
387         bool is_print_op = false;
388
389         /* can't fail if we don't try */
390
391         if ( !*cmd )
392                 return WERR_OK;
393
394         command = talloc_asprintf(ctx,
395                         "%s \"%s\"",
396                         cmd, sharename);
397         if (!command) {
398                 return WERR_NOMEM;
399         }
400         if ( token )
401                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
402
403         DEBUG(10,("Running [%s]\n", command));
404
405         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
406
407         if ( is_print_op )
408                 become_root();
409
410         if ( (ret = smbrun(command, NULL)) == 0 ) {
411                 /* Tell everyone we updated smb.conf. */
412                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
413         }
414
415         if ( is_print_op )
416                 unbecome_root();
417
418         /********** END SePrintOperatorPrivlege BLOCK **********/
419
420         DEBUGADD(10,("returned [%d]\n", ret));
421
422         TALLOC_FREE(command);
423
424         if (ret != 0)
425                 return WERR_BADFID; /* What to return here? */
426
427         /* go ahead and re-read the services immediately */
428         become_root();
429         reload_services(msg_ctx, -1, false);
430         unbecome_root();
431
432         if ( lp_servicenumber( sharename ) >= 0 )
433                 return WERR_ACCESS_DENIED;
434
435         return WERR_OK;
436 }
437
438 /****************************************************************************
439  Delete a printer given a handle.
440 ****************************************************************************/
441
442 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
443 {
444         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
445         WERROR result;
446
447         if (!Printer) {
448                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
449                         OUR_HANDLE(hnd)));
450                 return WERR_BADFID;
451         }
452
453         /*
454          * It turns out that Windows allows delete printer on a handle
455          * opened by an admin user, then used on a pipe handle created
456          * by an anonymous user..... but they're working on security.... riiight !
457          * JRA.
458          */
459
460         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
461                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
462                 return WERR_ACCESS_DENIED;
463         }
464
465         /* this does not need a become root since the access check has been
466            done on the handle already */
467
468         result = winreg_delete_printer_key_internal(p->mem_ctx,
469                                            get_session_info_system(),
470                                            p->msg_ctx,
471                                            Printer->sharename,
472                                            "");
473         if (!W_ERROR_IS_OK(result)) {
474                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
475                 return WERR_BADFID;
476         }
477
478         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
479                                      Printer->sharename, p->msg_ctx);
480         if (!W_ERROR_IS_OK(result)) {
481                 return result;
482         }
483         prune_printername_cache();
484         return WERR_OK;
485 }
486
487 /****************************************************************************
488  Return the snum of a printer corresponding to an handle.
489 ****************************************************************************/
490
491 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
492                              int *number, struct share_params **params)
493 {
494         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
495
496         if (!Printer) {
497                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
498                         OUR_HANDLE(hnd)));
499                 return false;
500         }
501
502         switch (Printer->printer_type) {
503                 case SPLHND_PRINTER:
504                         DEBUG(4,("short name:%s\n", Printer->sharename));
505                         *number = print_queue_snum(Printer->sharename);
506                         return (*number != -1);
507                 case SPLHND_SERVER:
508                         return false;
509                 default:
510                         return false;
511         }
512 }
513
514 /****************************************************************************
515  Set printer handle type.
516  Check if it's \\server or \\server\printer
517 ****************************************************************************/
518
519 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
520 {
521         DEBUG(3,("Setting printer type=%s\n", handlename));
522
523         /* it's a print server */
524         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
525                 DEBUGADD(4,("Printer is a print server\n"));
526                 Printer->printer_type = SPLHND_SERVER;
527         }
528         /* it's a printer (set_printer_hnd_name() will handle port monitors */
529         else {
530                 DEBUGADD(4,("Printer is a printer\n"));
531                 Printer->printer_type = SPLHND_PRINTER;
532         }
533
534         return true;
535 }
536
537 static void prune_printername_cache_fn(const char *key, const char *value,
538                                        time_t timeout, void *private_data)
539 {
540         gencache_del(key);
541 }
542
543 static void prune_printername_cache(void)
544 {
545         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
546 }
547
548 /****************************************************************************
549  Set printer handle name..  Accept names like \\server, \\server\printer,
550  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
551  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
552  XcvDataPort() interface.
553 ****************************************************************************/
554
555 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
556                                    const struct auth_serversupplied_info *session_info,
557                                    struct messaging_context *msg_ctx,
558                                    struct printer_handle *Printer,
559                                    const char *handlename)
560 {
561         int snum;
562         int n_services=lp_numservices();
563         char *aprinter;
564         const char *printername;
565         const char *servername = NULL;
566         fstring sname;
567         bool found = false;
568         struct spoolss_PrinterInfo2 *info2 = NULL;
569         WERROR result;
570         char *p;
571
572         /*
573          * Hopefully nobody names his printers like this. Maybe \ or ,
574          * are illegal in printer names even?
575          */
576         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
577         char *cache_key;
578         char *tmp;
579
580         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
581                 (unsigned long)strlen(handlename)));
582
583         aprinter = CONST_DISCARD(char *, handlename);
584         if ( *handlename == '\\' ) {
585                 servername = canon_servername(handlename);
586                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
587                         *aprinter = '\0';
588                         aprinter++;
589                 }
590                 if (!is_myname_or_ipaddr(servername)) {
591                         return WERR_INVALID_PRINTER_NAME;
592                 }
593                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
594                 if (Printer->servername == NULL) {
595                         return WERR_NOMEM;
596                 }
597         }
598
599         if (Printer->printer_type == SPLHND_SERVER) {
600                 return WERR_OK;
601         }
602
603         if (Printer->printer_type != SPLHND_PRINTER) {
604                 return WERR_INVALID_HANDLE;
605         }
606
607         DEBUGADD(5, ("searching for [%s]\n", aprinter));
608
609         p = strchr(aprinter, ',');
610         if (p != NULL) {
611                 char *p2 = p;
612                 p++;
613                 if (*p == ' ') {
614                         p++;
615                 }
616                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
617                         *p2 = '\0';
618                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
619                         *p2 = '\0';
620                 }
621         }
622
623         if (p) {
624                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
625         }
626
627         /* check for the Port Monitor Interface */
628         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
629                 Printer->printer_type = SPLHND_PORTMON_TCP;
630                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
631                 found = true;
632         }
633         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
634                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
635                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
636                 found = true;
637         }
638
639         /*
640          * With hundreds of printers, the "for" loop iterating all
641          * shares can be quite expensive, as it is done on every
642          * OpenPrinter. The loop maps "aprinter" to "sname", the
643          * result of which we cache in gencache.
644          */
645
646         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
647                                     aprinter);
648         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
649
650                 found = (strcmp(tmp, printer_not_found) != 0);
651                 if (!found) {
652                         DEBUG(4, ("Printer %s not found\n", aprinter));
653                         SAFE_FREE(tmp);
654                         return WERR_INVALID_PRINTER_NAME;
655                 }
656                 fstrcpy(sname, tmp);
657                 SAFE_FREE(tmp);
658         }
659
660         /* Search all sharenames first as this is easier than pulling
661            the printer_info_2 off of disk. Don't use find_service() since
662            that calls out to map_username() */
663
664         /* do another loop to look for printernames */
665         for (snum = 0; !found && snum < n_services; snum++) {
666                 const char *printer = lp_const_servicename(snum);
667
668                 /* no point going on if this is not a printer */
669                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
670                         continue;
671                 }
672
673                 /* ignore [printers] share */
674                 if (strequal(printer, "printers")) {
675                         continue;
676                 }
677
678                 fstrcpy(sname, printer);
679                 if (strequal(aprinter, printer)) {
680                         found = true;
681                         break;
682                 }
683
684                 /* no point looking up the printer object if
685                    we aren't allowing printername != sharename */
686                 if (lp_force_printername(snum)) {
687                         continue;
688                 }
689
690                 result = winreg_get_printer_internal(mem_ctx,
691                                             session_info,
692                                             msg_ctx,
693                                             sname,
694                                             &info2);
695                 if ( !W_ERROR_IS_OK(result) ) {
696                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
697                                  sname, win_errstr(result)));
698                         continue;
699                 }
700
701                 printername = strrchr(info2->printername, '\\');
702                 if (printername == NULL) {
703                         printername = info2->printername;
704                 } else {
705                         printername++;
706                 }
707
708                 if (strequal(printername, aprinter)) {
709                         found = true;
710                         break;
711                 }
712
713                 DEBUGADD(10, ("printername: %s\n", printername));
714
715                 TALLOC_FREE(info2);
716         }
717
718         if ( !found ) {
719                 if (cache_key != NULL) {
720                         gencache_set(cache_key, printer_not_found,
721                                      time(NULL)+300);
722                         TALLOC_FREE(cache_key);
723                 }
724                 DEBUGADD(4,("Printer not found\n"));
725                 return WERR_INVALID_PRINTER_NAME;
726         }
727
728         if (cache_key != NULL) {
729                 gencache_set(cache_key, sname, time(NULL)+300);
730                 TALLOC_FREE(cache_key);
731         }
732
733         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
734
735         fstrcpy(Printer->sharename, sname);
736
737         return WERR_OK;
738 }
739
740 /****************************************************************************
741  Find first available printer slot. creates a printer handle for you.
742  ****************************************************************************/
743
744 static WERROR open_printer_hnd(struct pipes_struct *p,
745                                struct policy_handle *hnd,
746                                const char *name,
747                                uint32_t access_granted)
748 {
749         struct printer_handle *new_printer;
750         WERROR result;
751
752         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
753
754         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
755         if (new_printer == NULL) {
756                 return WERR_NOMEM;
757         }
758         talloc_set_destructor(new_printer, printer_entry_destructor);
759
760         /* This also steals the printer_handle on the policy_handle */
761         if (!create_policy_hnd(p, hnd, new_printer)) {
762                 TALLOC_FREE(new_printer);
763                 return WERR_INVALID_HANDLE;
764         }
765
766         /* Add to the internal list. */
767         DLIST_ADD(printers_list, new_printer);
768
769         new_printer->notify.option=NULL;
770
771         if (!set_printer_hnd_printertype(new_printer, name)) {
772                 close_printer_handle(p, hnd);
773                 return WERR_INVALID_HANDLE;
774         }
775
776         result = set_printer_hnd_name(p->mem_ctx,
777                                       get_session_info_system(),
778                                       p->msg_ctx,
779                                       new_printer, name);
780         if (!W_ERROR_IS_OK(result)) {
781                 close_printer_handle(p, hnd);
782                 return result;
783         }
784
785         new_printer->access_granted = access_granted;
786
787         DEBUG(5, ("%d printer handles active\n",
788                   (int)num_pipe_handles(p)));
789
790         return WERR_OK;
791 }
792
793 /***************************************************************************
794  check to see if the client motify handle is monitoring the notification
795  given by (notify_type, notify_field).
796  **************************************************************************/
797
798 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
799                                       uint16_t notify_field)
800 {
801         return true;
802 }
803
804 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
805                                 uint16_t notify_field)
806 {
807         struct spoolss_NotifyOption *option = p->notify.option;
808         uint32_t i, j;
809
810         /*
811          * Flags should always be zero when the change notify
812          * is registered by the client's spooler.  A user Win32 app
813          * might use the flags though instead of the NOTIFY_OPTION_INFO
814          * --jerry
815          */
816
817         if (!option) {
818                 return false;
819         }
820
821         if (p->notify.flags)
822                 return is_monitoring_event_flags(
823                         p->notify.flags, notify_type, notify_field);
824
825         for (i = 0; i < option->count; i++) {
826
827                 /* Check match for notify_type */
828
829                 if (option->types[i].type != notify_type)
830                         continue;
831
832                 /* Check match for field */
833
834                 for (j = 0; j < option->types[i].count; j++) {
835                         if (option->types[i].fields[j].field == notify_field) {
836                                 return true;
837                         }
838                 }
839         }
840
841         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
842                    p->servername, p->sharename, notify_type, notify_field));
843
844         return false;
845 }
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
848         _data->data.integer[0] = _integer; \
849         _data->data.integer[1] = 0;
850
851
852 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
853         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
854         if (!_data->data.string.string) {\
855                 _data->data.string.size = 0; \
856         } \
857         _data->data.string.size = strlen_m_term(_p) * 2;
858
859 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
860         _data->data.devmode.devmode = _devmode;
861
862 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
863         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
864         if (!_data->data.sd.sd) { \
865                 _data->data.sd.sd_size = 0; \
866         } \
867         _data->data.sd.sd_size = \
868                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
869
870 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
871                                    struct tm *t,
872                                    const char **pp,
873                                    uint32_t *plen)
874 {
875         struct spoolss_Time st;
876         uint32_t len = 16;
877         char *p;
878
879         if (!init_systemtime(&st, t)) {
880                 return;
881         }
882
883         p = talloc_array(mem_ctx, char, len);
884         if (!p) {
885                 return;
886         }
887
888         /*
889          * Systemtime must be linearized as a set of UINT16's.
890          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
891          */
892
893         SSVAL(p, 0, st.year);
894         SSVAL(p, 2, st.month);
895         SSVAL(p, 4, st.day_of_week);
896         SSVAL(p, 6, st.day);
897         SSVAL(p, 8, st.hour);
898         SSVAL(p, 10, st.minute);
899         SSVAL(p, 12, st.second);
900         SSVAL(p, 14, st.millisecond);
901
902         *pp = p;
903         *plen = len;
904 }
905
906 /* Convert a notification message to a struct spoolss_Notify */
907
908 static void notify_one_value(struct spoolss_notify_msg *msg,
909                              struct spoolss_Notify *data,
910                              TALLOC_CTX *mem_ctx)
911 {
912         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
913 }
914
915 static void notify_string(struct spoolss_notify_msg *msg,
916                           struct spoolss_Notify *data,
917                           TALLOC_CTX *mem_ctx)
918 {
919         /* The length of the message includes the trailing \0 */
920
921         data->data.string.size = msg->len * 2;
922         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
923         if (!data->data.string.string) {
924                 data->data.string.size = 0;
925                 return;
926         }
927 }
928
929 static void notify_system_time(struct spoolss_notify_msg *msg,
930                                struct spoolss_Notify *data,
931                                TALLOC_CTX *mem_ctx)
932 {
933         data->data.string.string = NULL;
934         data->data.string.size = 0;
935
936         if (msg->len != sizeof(time_t)) {
937                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
938                           msg->len));
939                 return;
940         }
941
942         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
943                                &data->data.string.string,
944                                &data->data.string.size);
945 }
946
947 struct notify2_message_table {
948         const char *name;
949         void (*fn)(struct spoolss_notify_msg *msg,
950                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
951 };
952
953 static struct notify2_message_table printer_notify_table[] = {
954         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
955         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
956         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
957         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
958         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
959         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
960         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
961         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
962         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
963         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
964         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
965         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
966         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
967         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
968         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
969         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
970         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
971         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
972         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
973 };
974
975 static struct notify2_message_table job_notify_table[] = {
976         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
977         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
978         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
979         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
980         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
981         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
982         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
983         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
984         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
985         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
986         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
987         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
988         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
989         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
990         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
991         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
992         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
993         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
994         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
995         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
996         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
997         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
998         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
999         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1000 };
1001
1002
1003 /***********************************************************************
1004  Allocate talloc context for container object
1005  **********************************************************************/
1006
1007 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1008 {
1009         if ( !ctr )
1010                 return;
1011
1012         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1013
1014         return;
1015 }
1016
1017 /***********************************************************************
1018  release all allocated memory and zero out structure
1019  **********************************************************************/
1020
1021 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1022 {
1023         if ( !ctr )
1024                 return;
1025
1026         if ( ctr->ctx )
1027                 talloc_destroy(ctr->ctx);
1028
1029         ZERO_STRUCTP(ctr);
1030
1031         return;
1032 }
1033
1034 /***********************************************************************
1035  **********************************************************************/
1036
1037 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1038 {
1039         if ( !ctr )
1040                 return NULL;
1041
1042         return ctr->ctx;
1043 }
1044
1045 /***********************************************************************
1046  **********************************************************************/
1047
1048 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1049 {
1050         if ( !ctr || !ctr->msg_groups )
1051                 return NULL;
1052
1053         if ( idx >= ctr->num_groups )
1054                 return NULL;
1055
1056         return &ctr->msg_groups[idx];
1057
1058 }
1059
1060 /***********************************************************************
1061  How many groups of change messages do we have ?
1062  **********************************************************************/
1063
1064 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1065 {
1066         if ( !ctr )
1067                 return 0;
1068
1069         return ctr->num_groups;
1070 }
1071
1072 /***********************************************************************
1073  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1074  **********************************************************************/
1075
1076 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1077 {
1078         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1079         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1080         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1081         int                             i, new_slot;
1082
1083         if ( !ctr || !msg )
1084                 return 0;
1085
1086         /* loop over all groups looking for a matching printer name */
1087
1088         for ( i=0; i<ctr->num_groups; i++ ) {
1089                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1090                         break;
1091         }
1092
1093         /* add a new group? */
1094
1095         if ( i == ctr->num_groups ) {
1096                 ctr->num_groups++;
1097
1098                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1099                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1100                         return 0;
1101                 }
1102                 ctr->msg_groups = groups;
1103
1104                 /* clear the new entry and set the printer name */
1105
1106                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1107                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1108         }
1109
1110         /* add the change messages; 'i' is the correct index now regardless */
1111
1112         msg_grp = &ctr->msg_groups[i];
1113
1114         msg_grp->num_msgs++;
1115
1116         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1117                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1118                 return 0;
1119         }
1120         msg_grp->msgs = msg_list;
1121
1122         new_slot = msg_grp->num_msgs-1;
1123         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1124
1125         /* need to allocate own copy of data */
1126
1127         if ( msg->len != 0 )
1128                 msg_grp->msgs[new_slot].notify.data = (char *)
1129                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1130
1131         return ctr->num_groups;
1132 }
1133
1134 static void construct_info_data(struct spoolss_Notify *info_data,
1135                                 enum spoolss_NotifyType type,
1136                                 uint16_t field, int id);
1137
1138 /***********************************************************************
1139  Send a change notication message on all handles which have a call
1140  back registered
1141  **********************************************************************/
1142
1143 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1144                                   struct printer_handle *prn_hnd,
1145                                   SPOOLSS_NOTIFY_MSG *messages,
1146                                   uint32_t num_msgs,
1147                                   struct spoolss_Notify **_notifies,
1148                                   int *_count)
1149 {
1150         struct spoolss_Notify *notifies;
1151         SPOOLSS_NOTIFY_MSG *msg;
1152         int count = 0;
1153         uint32_t id;
1154         int i;
1155
1156         notifies = talloc_zero_array(mem_ctx,
1157                                      struct spoolss_Notify, num_msgs);
1158         if (!notifies) {
1159                 return ENOMEM;
1160         }
1161
1162         for (i = 0; i < num_msgs; i++) {
1163
1164                 msg = &messages[i];
1165
1166                 /* Are we monitoring this event? */
1167
1168                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1169                         continue;
1170                 }
1171
1172                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1173                            "for printer [%s]\n",
1174                            msg->type, msg->field, prn_hnd->sharename));
1175
1176                 /*
1177                  * if the is a printer notification handle and not a job
1178                  * notification type, then set the id to 0.
1179                  * Otherwise just use what was specified in the message.
1180                  *
1181                  * When registering change notification on a print server
1182                  * handle we always need to send back the id (snum) matching
1183                  * the printer for which the change took place.
1184                  * For change notify registered on a printer handle,
1185                  * this does not matter and the id should be 0.
1186                  *
1187                  * --jerry
1188                  */
1189
1190                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1191                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1192                         id = 0;
1193                 } else {
1194                         id = msg->id;
1195                 }
1196
1197                 /* Convert unix jobid to smb jobid */
1198
1199                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1200                         id = sysjob_to_jobid(msg->id);
1201
1202                         if (id == -1) {
1203                                 DEBUG(3, ("no such unix jobid %d\n",
1204                                           msg->id));
1205                                 continue;
1206                         }
1207                 }
1208
1209                 construct_info_data(&notifies[count],
1210                                     msg->type, msg->field, id);
1211
1212                 switch(msg->type) {
1213                 case PRINTER_NOTIFY_TYPE:
1214                         if (printer_notify_table[msg->field].fn) {
1215                                 printer_notify_table[msg->field].fn(msg,
1216                                                 &notifies[count], mem_ctx);
1217                         }
1218                         break;
1219
1220                 case JOB_NOTIFY_TYPE:
1221                         if (job_notify_table[msg->field].fn) {
1222                                 job_notify_table[msg->field].fn(msg,
1223                                                 &notifies[count], mem_ctx);
1224                         }
1225                         break;
1226
1227                 default:
1228                         DEBUG(5, ("Unknown notification type %d\n",
1229                                   msg->type));
1230                         continue;
1231                 }
1232
1233                 count++;
1234         }
1235
1236         *_notifies = notifies;
1237         *_count = count;
1238
1239         return 0;
1240 }
1241
1242 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1243                                 struct printer_handle *prn_hnd,
1244                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1245 {
1246         struct spoolss_Notify *notifies;
1247         int count = 0;
1248         union spoolss_ReplyPrinterInfo info;
1249         struct spoolss_NotifyInfo info0;
1250         uint32_t reply_result;
1251         NTSTATUS status;
1252         WERROR werr;
1253         int ret;
1254
1255         /* Is there notification on this handle? */
1256         if (prn_hnd->notify.cli_chan == NULL ||
1257             prn_hnd->notify.cli_chan->active_connections == 0) {
1258                 return 0;
1259         }
1260
1261         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1262                    prn_hnd->servername, prn_hnd->sharename));
1263
1264         /* For this printer? Print servers always receive notifications. */
1265         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1266             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1267                 return 0;
1268         }
1269
1270         DEBUG(10,("Our printer\n"));
1271
1272         /* build the array of change notifications */
1273         ret = build_notify2_messages(mem_ctx, prn_hnd,
1274                                      msg_group->msgs,
1275                                      msg_group->num_msgs,
1276                                      &notifies, &count);
1277         if (ret) {
1278                 return ret;
1279         }
1280
1281         info0.version   = 0x2;
1282         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1283         info0.count     = count;
1284         info0.notifies  = notifies;
1285
1286         info.info0 = &info0;
1287
1288         status = dcerpc_spoolss_RouterReplyPrinterEx(
1289                                 prn_hnd->notify.cli_chan->binding_handle,
1290                                 mem_ctx,
1291                                 &prn_hnd->notify.cli_hnd,
1292                                 prn_hnd->notify.change, /* color */
1293                                 prn_hnd->notify.flags,
1294                                 &reply_result,
1295                                 0, /* reply_type, must be 0 */
1296                                 info, &werr);
1297         if (!NT_STATUS_IS_OK(status)) {
1298                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1299                           "failed: %s\n",
1300                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301                           nt_errstr(status)));
1302                 werr = ntstatus_to_werror(status);
1303         } else if (!W_ERROR_IS_OK(werr)) {
1304                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1305                           "failed: %s\n",
1306                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1307                           win_errstr(werr)));
1308         }
1309         switch (reply_result) {
1310         case 0:
1311                 break;
1312         case PRINTER_NOTIFY_INFO_DISCARDED:
1313         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1314         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1315                 break;
1316         default:
1317                 break;
1318         }
1319
1320         return 0;
1321 }
1322
1323 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1324 {
1325         struct printer_handle    *p;
1326         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1327         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1328         int ret;
1329
1330         if ( !msg_group ) {
1331                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1332                 return;
1333         }
1334
1335         if (!msg_group->msgs) {
1336                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1337                 return;
1338         }
1339
1340         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1341
1342         /* loop over all printers */
1343
1344         for (p = printers_list; p; p = p->next) {
1345                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1346                 if (ret) {
1347                         goto done;
1348                 }
1349         }
1350
1351 done:
1352         DEBUG(8,("send_notify2_changes: Exit...\n"));
1353         return;
1354 }
1355
1356 /***********************************************************************
1357  **********************************************************************/
1358
1359 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1360 {
1361
1362         uint32_t tv_sec, tv_usec;
1363         size_t offset = 0;
1364
1365         /* Unpack message */
1366
1367         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1368                              msg->printer);
1369
1370         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1371                                 &tv_sec, &tv_usec,
1372                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1373
1374         if (msg->len == 0)
1375                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1376                            &msg->notify.value[0], &msg->notify.value[1]);
1377         else
1378                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1379                            &msg->len, &msg->notify.data);
1380
1381         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1382                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1383
1384         tv->tv_sec = tv_sec;
1385         tv->tv_usec = tv_usec;
1386
1387         if (msg->len == 0)
1388                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1389                           msg->notify.value[1]));
1390         else
1391                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1392
1393         return true;
1394 }
1395
1396 /********************************************************************
1397  Receive a notify2 message list
1398  ********************************************************************/
1399
1400 static void receive_notify2_message_list(struct messaging_context *msg,
1401                                          void *private_data,
1402                                          uint32_t msg_type,
1403                                          struct server_id server_id,
1404                                          DATA_BLOB *data)
1405 {
1406         size_t                  msg_count, i;
1407         char                    *buf = (char *)data->data;
1408         char                    *msg_ptr;
1409         size_t                  msg_len;
1410         SPOOLSS_NOTIFY_MSG      notify;
1411         SPOOLSS_NOTIFY_MSG_CTR  messages;
1412         int                     num_groups;
1413
1414         if (data->length < 4) {
1415                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1416                 return;
1417         }
1418
1419         msg_count = IVAL(buf, 0);
1420         msg_ptr = buf + 4;
1421
1422         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1423
1424         if (msg_count == 0) {
1425                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1426                 return;
1427         }
1428
1429         /* initialize the container */
1430
1431         ZERO_STRUCT( messages );
1432         notify_msg_ctr_init( &messages );
1433
1434         /*
1435          * build message groups for each printer identified
1436          * in a change_notify msg.  Remember that a PCN message
1437          * includes the handle returned for the srv_spoolss_replyopenprinter()
1438          * call.  Therefore messages are grouped according to printer handle.
1439          */
1440
1441         for ( i=0; i<msg_count; i++ ) {
1442                 struct timeval msg_tv;
1443
1444                 if (msg_ptr + 4 - buf > data->length) {
1445                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1446                         return;
1447                 }
1448
1449                 msg_len = IVAL(msg_ptr,0);
1450                 msg_ptr += 4;
1451
1452                 if (msg_ptr + msg_len - buf > data->length) {
1453                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1454                         return;
1455                 }
1456
1457                 /* unpack messages */
1458
1459                 ZERO_STRUCT( notify );
1460                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1461                 msg_ptr += msg_len;
1462
1463                 /* add to correct list in container */
1464
1465                 notify_msg_ctr_addmsg( &messages, &notify );
1466
1467                 /* free memory that might have been allocated by notify2_unpack_msg() */
1468
1469                 if ( notify.len != 0 )
1470                         SAFE_FREE( notify.notify.data );
1471         }
1472
1473         /* process each group of messages */
1474
1475         num_groups = notify_msg_ctr_numgroups( &messages );
1476         for ( i=0; i<num_groups; i++ )
1477                 send_notify2_changes( &messages, i );
1478
1479
1480         /* cleanup */
1481
1482         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1483                 (uint32_t)msg_count ));
1484
1485         notify_msg_ctr_destroy( &messages );
1486
1487         return;
1488 }
1489
1490 /********************************************************************
1491  Send a message to ourself about new driver being installed
1492  so we can upgrade the information for each printer bound to this
1493  driver
1494  ********************************************************************/
1495
1496 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1497                                             struct messaging_context *msg_ctx)
1498 {
1499         int len = strlen(drivername);
1500
1501         if (!len)
1502                 return false;
1503
1504         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1505                 drivername));
1506
1507         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1508                            MSG_PRINTER_DRVUPGRADE,
1509                            (uint8_t *)drivername, len+1);
1510
1511         return true;
1512 }
1513
1514 void srv_spoolss_cleanup(void)
1515 {
1516         struct printer_session_counter *session_counter;
1517
1518         for (session_counter = counter_list;
1519              session_counter != NULL;
1520              session_counter = counter_list) {
1521                 DLIST_REMOVE(counter_list, session_counter);
1522                 TALLOC_FREE(session_counter);
1523         }
1524 }
1525
1526 /**********************************************************************
1527  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1528  over all printers, upgrading ones as necessary
1529  **********************************************************************/
1530
1531 void do_drv_upgrade_printer(struct messaging_context *msg,
1532                             void *private_data,
1533                             uint32_t msg_type,
1534                             struct server_id server_id,
1535                             DATA_BLOB *data)
1536 {
1537         TALLOC_CTX *tmp_ctx;
1538         struct auth_serversupplied_info *session_info = NULL;
1539         struct spoolss_PrinterInfo2 *pinfo2;
1540         NTSTATUS status;
1541         WERROR result;
1542         const char *drivername;
1543         int snum;
1544         int n_services = lp_numservices();
1545         struct dcerpc_binding_handle *b = NULL;
1546
1547         tmp_ctx = talloc_new(NULL);
1548         if (!tmp_ctx) return;
1549
1550         status = make_session_info_system(tmp_ctx, &session_info);
1551         if (!NT_STATUS_IS_OK(status)) {
1552                 DEBUG(0, ("do_drv_upgrade_printer: "
1553                           "Could not create system session_info\n"));
1554                 goto done;
1555         }
1556
1557         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1558         if (!drivername) {
1559                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1560                 goto done;
1561         }
1562
1563         DEBUG(10, ("do_drv_upgrade_printer: "
1564                    "Got message for new driver [%s]\n", drivername));
1565
1566         /* Iterate the printer list */
1567
1568         for (snum = 0; snum < n_services; snum++) {
1569                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1570                         continue;
1571                 }
1572
1573                 /* ignore [printers] share */
1574                 if (strequal(lp_const_servicename(snum), "printers")) {
1575                         continue;
1576                 }
1577
1578                 if (b == NULL) {
1579                         result = winreg_printer_binding_handle(tmp_ctx,
1580                                                                session_info,
1581                                                                msg,
1582                                                                &b);
1583                         if (!W_ERROR_IS_OK(result)) {
1584                                 break;
1585                         }
1586                 }
1587
1588                 result = winreg_get_printer(tmp_ctx, b,
1589                                             lp_const_servicename(snum),
1590                                             &pinfo2);
1591
1592                 if (!W_ERROR_IS_OK(result)) {
1593                         continue;
1594                 }
1595
1596                 if (!pinfo2->drivername) {
1597                         continue;
1598                 }
1599
1600                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1601                         continue;
1602                 }
1603
1604                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1605
1606                 /* all we care about currently is the change_id */
1607                 result = winreg_printer_update_changeid(tmp_ctx, b,
1608                                                         pinfo2->printername);
1609
1610                 if (!W_ERROR_IS_OK(result)) {
1611                         DEBUG(3, ("do_drv_upgrade_printer: "
1612                                   "Failed to update changeid [%s]\n",
1613                                   win_errstr(result)));
1614                 }
1615         }
1616
1617         /* all done */
1618 done:
1619         talloc_free(tmp_ctx);
1620 }
1621
1622 /********************************************************************
1623  Update the cache for all printq's with a registered client
1624  connection
1625  ********************************************************************/
1626
1627 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1628 {
1629         struct printer_handle *printer = printers_list;
1630         int snum;
1631
1632         /* loop through all printers and update the cache where
1633            a client is connected */
1634         while (printer) {
1635                 if ((printer->printer_type == SPLHND_PRINTER) &&
1636                     ((printer->notify.cli_chan != NULL) &&
1637                      (printer->notify.cli_chan->active_connections > 0))) {
1638                         snum = print_queue_snum(printer->sharename);
1639                         print_queue_status(msg_ctx, snum, NULL, NULL);
1640                 }
1641
1642                 printer = printer->next;
1643         }
1644
1645         return;
1646 }
1647
1648 /****************************************************************
1649  _spoolss_OpenPrinter
1650 ****************************************************************/
1651
1652 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1653                             struct spoolss_OpenPrinter *r)
1654 {
1655         struct spoolss_OpenPrinterEx e;
1656         WERROR werr;
1657
1658         ZERO_STRUCT(e.in.userlevel);
1659
1660         e.in.printername        = r->in.printername;
1661         e.in.datatype           = r->in.datatype;
1662         e.in.devmode_ctr        = r->in.devmode_ctr;
1663         e.in.access_mask        = r->in.access_mask;
1664         e.in.level              = 0;
1665
1666         e.out.handle            = r->out.handle;
1667
1668         werr = _spoolss_OpenPrinterEx(p, &e);
1669
1670         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1671                 /* OpenPrinterEx returns this for a bad
1672                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1673                  * instead.
1674                  */
1675                 werr = WERR_INVALID_PRINTER_NAME;
1676         }
1677
1678         return werr;
1679 }
1680
1681 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1682                               struct spoolss_DeviceMode *orig,
1683                               struct spoolss_DeviceMode **dest)
1684 {
1685         struct spoolss_DeviceMode *dm;
1686
1687         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1688         if (!dm) {
1689                 return WERR_NOMEM;
1690         }
1691
1692         /* copy all values, then duplicate strings and structs */
1693         *dm = *orig;
1694
1695         dm->devicename = talloc_strdup(dm, orig->devicename);
1696         if (!dm->devicename) {
1697                 return WERR_NOMEM;
1698         }
1699         dm->formname = talloc_strdup(dm, orig->formname);
1700         if (!dm->formname) {
1701                 return WERR_NOMEM;
1702         }
1703         if (orig->driverextra_data.data) {
1704                 dm->driverextra_data.data =
1705                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1706                                         orig->driverextra_data.length);
1707                 if (!dm->driverextra_data.data) {
1708                         return WERR_NOMEM;
1709                 }
1710         }
1711
1712         *dest = dm;
1713         return WERR_OK;
1714 }
1715
1716 /****************************************************************
1717  _spoolss_OpenPrinterEx
1718 ****************************************************************/
1719
1720 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1721                               struct spoolss_OpenPrinterEx *r)
1722 {
1723         int snum;
1724         struct printer_handle *Printer=NULL;
1725         WERROR result;
1726
1727         if (!r->in.printername) {
1728                 return WERR_INVALID_PARAM;
1729         }
1730
1731         if (r->in.level > 3) {
1732                 return WERR_INVALID_PARAM;
1733         }
1734         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1735             (r->in.level == 2 && !r->in.userlevel.level2) ||
1736             (r->in.level == 3 && !r->in.userlevel.level3)) {
1737                 return WERR_INVALID_PARAM;
1738         }
1739
1740         /* some sanity check because you can open a printer or a print server */
1741         /* aka: \\server\printer or \\server */
1742
1743         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1744
1745         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1746         if (!W_ERROR_IS_OK(result)) {
1747                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1748                         "for printer %s\n", r->in.printername));
1749                 ZERO_STRUCTP(r->out.handle);
1750                 return result;
1751         }
1752
1753         Printer = find_printer_index_by_hnd(p, r->out.handle);
1754         if ( !Printer ) {
1755                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1756                         "handle we created for printer %s\n", r->in.printername));
1757                 close_printer_handle(p, r->out.handle);
1758                 ZERO_STRUCTP(r->out.handle);
1759                 return WERR_INVALID_PARAM;
1760         }
1761
1762         /*
1763          * First case: the user is opening the print server:
1764          *
1765          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1766          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1767          *
1768          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1769          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1770          * or if the user is listed in the smb.conf printer admin parameter.
1771          *
1772          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1773          * client view printer folder, but does not show the MSAPW.
1774          *
1775          * Note: this test needs code to check access rights here too. Jeremy
1776          * could you look at this?
1777          *
1778          * Second case: the user is opening a printer:
1779          * NT doesn't let us connect to a printer if the connecting user
1780          * doesn't have print permission.
1781          *
1782          * Third case: user is opening a Port Monitor
1783          * access checks same as opening a handle to the print server.
1784          */
1785
1786         switch (Printer->printer_type )
1787         {
1788         case SPLHND_SERVER:
1789         case SPLHND_PORTMON_TCP:
1790         case SPLHND_PORTMON_LOCAL:
1791                 /* Printserver handles use global struct... */
1792
1793                 snum = -1;
1794
1795                 /* Map standard access rights to object specific access rights */
1796
1797                 se_map_standard(&r->in.access_mask,
1798                                 &printserver_std_mapping);
1799
1800                 /* Deny any object specific bits that don't apply to print
1801                    servers (i.e printer and job specific bits) */
1802
1803                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1804
1805                 if (r->in.access_mask &
1806                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1807                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1808                         close_printer_handle(p, r->out.handle);
1809                         ZERO_STRUCTP(r->out.handle);
1810                         return WERR_ACCESS_DENIED;
1811                 }
1812
1813                 /* Allow admin access */
1814
1815                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1816                 {
1817                         if (!lp_ms_add_printer_wizard()) {
1818                                 close_printer_handle(p, r->out.handle);
1819                                 ZERO_STRUCTP(r->out.handle);
1820                                 return WERR_ACCESS_DENIED;
1821                         }
1822
1823                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1824                            and not a printer admin, then fail */
1825
1826                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1827                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1828                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1829                             !token_contains_name_in_list(
1830                                     uidtoname(p->session_info->utok.uid),
1831                                     p->session_info->info3->base.domain.string,
1832                                     NULL,
1833                                     p->session_info->security_token,
1834                                     lp_printer_admin(snum))) {
1835                                 close_printer_handle(p, r->out.handle);
1836                                 ZERO_STRUCTP(r->out.handle);
1837                                 DEBUG(3,("access DENIED as user is not root, "
1838                                         "has no printoperator privilege, "
1839                                         "not a member of the printoperator builtin group and "
1840                                         "is not in printer admin list"));
1841                                 return WERR_ACCESS_DENIED;
1842                         }
1843
1844                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1845                 }
1846                 else
1847                 {
1848                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1849                 }
1850
1851                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1852                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1853
1854                 /* We fall through to return WERR_OK */
1855                 break;
1856
1857         case SPLHND_PRINTER:
1858                 /* NT doesn't let us connect to a printer if the connecting user
1859                    doesn't have print permission.  */
1860
1861                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1862                         close_printer_handle(p, r->out.handle);
1863                         ZERO_STRUCTP(r->out.handle);
1864                         return WERR_BADFID;
1865                 }
1866
1867                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1868                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1869                 }
1870
1871                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1872
1873                 /* map an empty access mask to the minimum access mask */
1874                 if (r->in.access_mask == 0x0)
1875                         r->in.access_mask = PRINTER_ACCESS_USE;
1876
1877                 /*
1878                  * If we are not serving the printer driver for this printer,
1879                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1880                  * will keep NT clients happy  --jerry
1881                  */
1882
1883                 if (lp_use_client_driver(snum)
1884                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1885                 {
1886                         r->in.access_mask = PRINTER_ACCESS_USE;
1887                 }
1888
1889                 /* check smb.conf parameters and the the sec_desc */
1890
1891                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1892                                   p->client_id->name, p->client_id->addr)) {
1893                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894                         ZERO_STRUCTP(r->out.handle);
1895                         return WERR_ACCESS_DENIED;
1896                 }
1897
1898                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1899                                    p->session_info->security_token, snum) ||
1900                     !print_access_check(p->session_info,
1901                                         p->msg_ctx,
1902                                         snum,
1903                                         r->in.access_mask)) {
1904                         DEBUG(3, ("access DENIED for printer open\n"));
1905                         close_printer_handle(p, r->out.handle);
1906                         ZERO_STRUCTP(r->out.handle);
1907                         return WERR_ACCESS_DENIED;
1908                 }
1909
1910                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912                         close_printer_handle(p, r->out.handle);
1913                         ZERO_STRUCTP(r->out.handle);
1914                         return WERR_ACCESS_DENIED;
1915                 }
1916
1917                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919                 else
1920                         r->in.access_mask = PRINTER_ACCESS_USE;
1921
1922                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924
1925                 winreg_create_printer_internal(p->mem_ctx,
1926                                       get_session_info_system(),
1927                                       p->msg_ctx,
1928                                       lp_const_servicename(snum));
1929
1930                 break;
1931
1932         default:
1933                 /* sanity check to prevent programmer error */
1934                 ZERO_STRUCTP(r->out.handle);
1935                 return WERR_BADFID;
1936         }
1937
1938         Printer->access_granted = r->in.access_mask;
1939
1940         /*
1941          * If the client sent a devmode in the OpenPrinter() call, then
1942          * save it here in case we get a job submission on this handle
1943          */
1944
1945          if ((Printer->printer_type != SPLHND_SERVER) &&
1946              r->in.devmode_ctr.devmode) {
1947                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948                                 &Printer->devmode);
1949          }
1950
1951 #if 0   /* JERRY -- I'm doubtful this is really effective */
1952         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953            optimization in Windows 2000 clients  --jerry */
1954
1955         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1956                 && (RA_WIN2K == get_remote_arch()) )
1957         {
1958                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1959                 sys_usleep( 500000 );
1960         }
1961 #endif
1962
1963         return WERR_OK;
1964 }
1965
1966 /****************************************************************
1967  _spoolss_ClosePrinter
1968 ****************************************************************/
1969
1970 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1971                              struct spoolss_ClosePrinter *r)
1972 {
1973         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1974
1975         if (Printer && Printer->document_started) {
1976                 struct spoolss_EndDocPrinter e;
1977
1978                 e.in.handle = r->in.handle;
1979
1980                 _spoolss_EndDocPrinter(p, &e);
1981         }
1982
1983         if (!close_printer_handle(p, r->in.handle))
1984                 return WERR_BADFID;
1985
1986         /* clear the returned printer handle.  Observed behavior
1987            from Win2k server.  Don't think this really matters.
1988            Previous code just copied the value of the closed
1989            handle.    --jerry */
1990
1991         ZERO_STRUCTP(r->out.handle);
1992
1993         return WERR_OK;
1994 }
1995
1996 /****************************************************************
1997  _spoolss_DeletePrinter
1998 ****************************************************************/
1999
2000 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2001                               struct spoolss_DeletePrinter *r)
2002 {
2003         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2004         WERROR result;
2005         int snum;
2006
2007         if (Printer && Printer->document_started) {
2008                 struct spoolss_EndDocPrinter e;
2009
2010                 e.in.handle = r->in.handle;
2011
2012                 _spoolss_EndDocPrinter(p, &e);
2013         }
2014
2015         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2016                 winreg_delete_printer_key_internal(p->mem_ctx,
2017                                           get_session_info_system(),
2018                                           p->msg_ctx,
2019                                           lp_const_servicename(snum),
2020                                           "");
2021         }
2022
2023         result = delete_printer_handle(p, r->in.handle);
2024
2025         return result;
2026 }
2027
2028 /*******************************************************************
2029  * static function to lookup the version id corresponding to an
2030  * long architecture string
2031  ******************************************************************/
2032
2033 static const struct print_architecture_table_node archi_table[]= {
2034
2035         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2036         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2037         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2038         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2039         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2040         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2041         {"Windows x64",          SPL_ARCH_X64,          3 },
2042         {NULL,                   "",            -1 }
2043 };
2044
2045 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2046                                    SPOOLSS_DRIVER_VERSION_NT35,
2047                                    SPOOLSS_DRIVER_VERSION_NT4,
2048                                    SPOOLSS_DRIVER_VERSION_200X,
2049                                    -1};
2050
2051 static int get_version_id(const char *arch)
2052 {
2053         int i;
2054
2055         for (i=0; archi_table[i].long_archi != NULL; i++)
2056         {
2057                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2058                         return (archi_table[i].version);
2059         }
2060
2061         return -1;
2062 }
2063
2064 /****************************************************************
2065  _spoolss_DeletePrinterDriver
2066 ****************************************************************/
2067
2068 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2069                                     struct spoolss_DeletePrinterDriver *r)
2070 {
2071
2072         struct spoolss_DriverInfo8 *info = NULL;
2073         int                             version;
2074         WERROR                          status;
2075         struct dcerpc_binding_handle *b;
2076         TALLOC_CTX *tmp_ctx = NULL;
2077         int i;
2078         bool found;
2079
2080         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2081            and not a printer admin, then fail */
2082
2083         if ( (p->session_info->utok.uid != sec_initial_uid())
2084              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2085                 && !token_contains_name_in_list(
2086                         uidtoname(p->session_info->utok.uid),
2087                         p->session_info->info3->base.domain.string,
2088                         NULL,
2089                         p->session_info->security_token,
2090                         lp_printer_admin(-1)) )
2091         {
2092                 return WERR_ACCESS_DENIED;
2093         }
2094
2095         /* check that we have a valid driver name first */
2096
2097         if ((version = get_version_id(r->in.architecture)) == -1)
2098                 return WERR_INVALID_ENVIRONMENT;
2099
2100         tmp_ctx = talloc_new(p->mem_ctx);
2101         if (!tmp_ctx) {
2102                 return WERR_NOMEM;
2103         }
2104
2105         status = winreg_printer_binding_handle(tmp_ctx,
2106                                                get_session_info_system(),
2107                                                p->msg_ctx,
2108                                                &b);
2109         if (!W_ERROR_IS_OK(status)) {
2110                 goto done;
2111         }
2112
2113         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2114                 status = winreg_get_driver(tmp_ctx, b,
2115                                            r->in.architecture, r->in.driver,
2116                                            drv_cversion[i], &info);
2117                 if (!W_ERROR_IS_OK(status)) {
2118                         DEBUG(5, ("skipping del of driver with version %d\n",
2119                                   drv_cversion[i]));
2120                         continue;
2121                 }
2122                 found = true;
2123
2124                 if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
2125                                           p->msg_ctx, info)) {
2126                         status = WERR_PRINTER_DRIVER_IN_USE;
2127                         goto done;
2128                 }
2129
2130                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2131                 if (!W_ERROR_IS_OK(status)) {
2132                         DEBUG(0, ("failed del of driver with version %d\n",
2133                                   drv_cversion[i]));
2134                         goto done;
2135                 }
2136         }
2137         if (found == false) {
2138                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2139                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2140         } else {
2141                 status = WERR_OK;
2142         }
2143
2144 done:
2145         talloc_free(tmp_ctx);
2146         return status;
2147 }
2148
2149 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2150                                   struct pipes_struct *p,
2151                                   struct spoolss_DeletePrinterDriverEx *r,
2152                                   struct dcerpc_binding_handle *b,
2153                                   struct spoolss_DriverInfo8 *info)
2154 {
2155         WERROR status;
2156         bool delete_files;
2157
2158         if (printer_driver_in_use(mem_ctx, get_session_info_system(),
2159                                   p->msg_ctx, info)) {
2160                 status = WERR_PRINTER_DRIVER_IN_USE;
2161                 goto done;
2162         }
2163
2164         /*
2165          * we have a couple of cases to consider.
2166          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2167          *     then the delete should fail if **any** files overlap with
2168          *     other drivers
2169          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2170          *     non-overlapping files
2171          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2172          *     is set, then do not delete any files
2173          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2174          */
2175
2176         delete_files = r->in.delete_flags
2177                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2178
2179         if (delete_files) {
2180                 bool in_use = printer_driver_files_in_use(mem_ctx,
2181                                                 get_session_info_system(),
2182                                                           p->msg_ctx,
2183                                                           info);
2184                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2185                         status = WERR_PRINTER_DRIVER_IN_USE;
2186                         goto done;
2187                 }
2188                 /*
2189                  * printer_driver_files_in_use() has trimmed overlapping files
2190                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2191                  */
2192         }
2193
2194         status = winreg_del_driver(mem_ctx, b, info, info->version);
2195         if (!W_ERROR_IS_OK(status)) {
2196                 goto done;
2197         }
2198
2199         /*
2200          * now delete any associated files if delete_files is
2201          * true. Even if this part failes, we return succes
2202          * because the driver doesn not exist any more
2203          */
2204         if (delete_files) {
2205                 delete_driver_files(get_session_info_system(), info);
2206         }
2207
2208 done:
2209         return status;
2210 }
2211
2212 /****************************************************************
2213  _spoolss_DeletePrinterDriverEx
2214 ****************************************************************/
2215
2216 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2217                                       struct spoolss_DeletePrinterDriverEx *r)
2218 {
2219         struct spoolss_DriverInfo8 *info = NULL;
2220         WERROR                          status;
2221         struct dcerpc_binding_handle *b;
2222         TALLOC_CTX *tmp_ctx = NULL;
2223         int i;
2224         bool found;
2225
2226         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2227            and not a printer admin, then fail */
2228
2229         if ( (p->session_info->utok.uid != sec_initial_uid())
2230                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2231                 && !token_contains_name_in_list(
2232                         uidtoname(p->session_info->utok.uid),
2233                         p->session_info->info3->base.domain.string,
2234                         NULL,
2235                         p->session_info->security_token, lp_printer_admin(-1)) )
2236         {
2237                 return WERR_ACCESS_DENIED;
2238         }
2239
2240         /* check that we have a valid driver name first */
2241         if (get_version_id(r->in.architecture) == -1) {
2242                 /* this is what NT returns */
2243                 return WERR_INVALID_ENVIRONMENT;
2244         }
2245
2246         tmp_ctx = talloc_new(p->mem_ctx);
2247         if (!tmp_ctx) {
2248                 return WERR_NOMEM;
2249         }
2250
2251         status = winreg_printer_binding_handle(tmp_ctx,
2252                                                get_session_info_system(),
2253                                                p->msg_ctx,
2254                                                &b);
2255         if (!W_ERROR_IS_OK(status)) {
2256                 goto done;
2257         }
2258
2259         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2260                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2261                  && (drv_cversion[i] != r->in.version)) {
2262                         continue;
2263                 }
2264
2265                 /* check if a driver with this version exists before delete */
2266                 status = winreg_get_driver(tmp_ctx, b,
2267                                            r->in.architecture, r->in.driver,
2268                                            drv_cversion[i], &info);
2269                 if (!W_ERROR_IS_OK(status)) {
2270                         DEBUG(5, ("skipping del of driver with version %d\n",
2271                                   drv_cversion[i]));
2272                         continue;
2273                 }
2274                 found = true;
2275
2276                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2277                 if (!W_ERROR_IS_OK(status)) {
2278                         DEBUG(0, ("failed to delete driver with version %d\n",
2279                                   drv_cversion[i]));
2280                         goto done;
2281                 }
2282         }
2283         if (found == false) {
2284                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2285                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2286         } else {
2287                 status = WERR_OK;
2288         }
2289
2290 done:
2291         talloc_free(tmp_ctx);
2292         return status;
2293 }
2294
2295
2296 /********************************************************************
2297  GetPrinterData on a printer server Handle.
2298 ********************************************************************/
2299
2300 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2301                                             const char *value,
2302                                             enum winreg_Type *type,
2303                                             union spoolss_PrinterData *data)
2304 {
2305         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2306
2307         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2308                 *type = REG_DWORD;
2309                 data->value = 0x00;
2310                 return WERR_OK;
2311         }
2312
2313         if (!StrCaseCmp(value, "BeepEnabled")) {
2314                 *type = REG_DWORD;
2315                 data->value = 0x00;
2316                 return WERR_OK;
2317         }
2318
2319         if (!StrCaseCmp(value, "EventLog")) {
2320                 *type = REG_DWORD;
2321                 /* formally was 0x1b */
2322                 data->value = 0x00;
2323                 return WERR_OK;
2324         }
2325
2326         if (!StrCaseCmp(value, "NetPopup")) {
2327                 *type = REG_DWORD;
2328                 data->value = 0x00;
2329                 return WERR_OK;
2330         }
2331
2332         if (!StrCaseCmp(value, "MajorVersion")) {
2333                 *type = REG_DWORD;
2334
2335                 /* Windows NT 4.0 seems to not allow uploading of drivers
2336                    to a server that reports 0x3 as the MajorVersion.
2337                    need to investigate more how Win2k gets around this .
2338                    -- jerry */
2339
2340                 if (RA_WINNT == get_remote_arch()) {
2341                         data->value = 0x02;
2342                 } else {
2343                         data->value = 0x03;
2344                 }
2345
2346                 return WERR_OK;
2347         }
2348
2349         if (!StrCaseCmp(value, "MinorVersion")) {
2350                 *type = REG_DWORD;
2351                 data->value = 0x00;
2352                 return WERR_OK;
2353         }
2354
2355         /* REG_BINARY
2356          *  uint32_t size        = 0x114
2357          *  uint32_t major       = 5
2358          *  uint32_t minor       = [0|1]
2359          *  uint32_t build       = [2195|2600]
2360          *  extra unicode string = e.g. "Service Pack 3"
2361          */
2362         if (!StrCaseCmp(value, "OSVersion")) {
2363                 DATA_BLOB blob;
2364                 enum ndr_err_code ndr_err;
2365                 struct spoolss_OSVersion os;
2366
2367                 os.major                = 5;    /* Windows 2000 == 5.0 */
2368                 os.minor                = 0;
2369                 os.build                = 2195; /* build */
2370                 os.extra_string         = "";   /* leave extra string empty */
2371
2372                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2373                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2374                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2375                         return WERR_GENERAL_FAILURE;
2376                 }
2377
2378                 *type = REG_BINARY;
2379                 data->binary = blob;
2380
2381                 return WERR_OK;
2382         }
2383
2384
2385         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2386                 *type = REG_SZ;
2387
2388                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2389                 W_ERROR_HAVE_NO_MEMORY(data->string);
2390
2391                 return WERR_OK;
2392         }
2393
2394         if (!StrCaseCmp(value, "Architecture")) {
2395                 *type = REG_SZ;
2396                 data->string = talloc_strdup(mem_ctx,
2397                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2398                 W_ERROR_HAVE_NO_MEMORY(data->string);
2399
2400                 return WERR_OK;
2401         }
2402
2403         if (!StrCaseCmp(value, "DsPresent")) {
2404                 *type = REG_DWORD;
2405
2406                 /* only show the publish check box if we are a
2407                    member of a AD domain */
2408
2409                 if (lp_security() == SEC_ADS) {
2410                         data->value = 0x01;
2411                 } else {
2412                         data->value = 0x00;
2413                 }
2414                 return WERR_OK;
2415         }
2416
2417         if (!StrCaseCmp(value, "DNSMachineName")) {
2418                 const char *hostname = get_mydnsfullname();
2419
2420                 if (!hostname) {
2421                         return WERR_BADFILE;
2422                 }
2423
2424                 *type = REG_SZ;
2425                 data->string = talloc_strdup(mem_ctx, hostname);
2426                 W_ERROR_HAVE_NO_MEMORY(data->string);
2427
2428                 return WERR_OK;
2429         }
2430
2431         *type = REG_NONE;
2432
2433         return WERR_INVALID_PARAM;
2434 }
2435
2436 /****************************************************************
2437  _spoolss_GetPrinterData
2438 ****************************************************************/
2439
2440 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2441                                struct spoolss_GetPrinterData *r)
2442 {
2443         struct spoolss_GetPrinterDataEx r2;
2444
2445         r2.in.handle            = r->in.handle;
2446         r2.in.key_name          = "PrinterDriverData";
2447         r2.in.value_name        = r->in.value_name;
2448         r2.in.offered           = r->in.offered;
2449         r2.out.type             = r->out.type;
2450         r2.out.data             = r->out.data;
2451         r2.out.needed           = r->out.needed;
2452
2453         return _spoolss_GetPrinterDataEx(p, &r2);
2454 }
2455
2456 /*********************************************************
2457  Connect to the client machine.
2458 **********************************************************/
2459
2460 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2461                         struct sockaddr_storage *client_ss, const char *remote_machine)
2462 {
2463         NTSTATUS ret;
2464         struct cli_state *the_cli;
2465         struct sockaddr_storage rm_addr;
2466         char addr[INET6_ADDRSTRLEN];
2467
2468         if ( is_zero_addr(client_ss) ) {
2469                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2470                         remote_machine));
2471                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2472                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2473                         return false;
2474                 }
2475                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2476         } else {
2477                 rm_addr = *client_ss;
2478                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2479                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2480                         addr));
2481         }
2482
2483         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2484                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2485                         addr));
2486                 return false;
2487         }
2488
2489         /* setup the connection */
2490         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2491                 &rm_addr, 0, "IPC$", "IPC",
2492                 "", /* username */
2493                 "", /* domain */
2494                 "", /* password */
2495                 0, lp_client_signing());
2496
2497         if ( !NT_STATUS_IS_OK( ret ) ) {
2498                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2499                         remote_machine ));
2500                 return false;
2501         }
2502
2503         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2504                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2505                 cli_shutdown(the_cli);
2506                 return false;
2507         }
2508
2509         /*
2510          * Ok - we have an anonymous connection to the IPC$ share.
2511          * Now start the NT Domain stuff :-).
2512          */
2513
2514         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2515         if (!NT_STATUS_IS_OK(ret)) {
2516                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2517                         remote_machine, nt_errstr(ret)));
2518                 cli_shutdown(the_cli);
2519                 return false;
2520         }
2521
2522         return true;
2523 }
2524
2525 /***************************************************************************
2526  Connect to the client.
2527 ****************************************************************************/
2528
2529 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2530                                         uint32_t localprinter,
2531                                         enum winreg_Type type,
2532                                         struct policy_handle *handle,
2533                                         struct notify_back_channel **_chan,
2534                                         struct sockaddr_storage *client_ss,
2535                                         struct messaging_context *msg_ctx)
2536 {
2537         WERROR result;
2538         NTSTATUS status;
2539         struct notify_back_channel *chan;
2540
2541         for (chan = back_channels; chan; chan = chan->next) {
2542                 if (memcmp(&chan->client_address, client_ss,
2543                            sizeof(struct sockaddr_storage)) == 0) {
2544                         break;
2545                 }
2546         }
2547
2548         /*
2549          * If it's the first connection, contact the client
2550          * and connect to the IPC$ share anonymously
2551          */
2552         if (!chan) {
2553                 fstring unix_printer;
2554
2555                 /* the +2 is to strip the leading 2 backslashs */
2556                 fstrcpy(unix_printer, printer + 2);
2557
2558                 chan = talloc_zero(back_channels, struct notify_back_channel);
2559                 if (!chan) {
2560                         return false;
2561                 }
2562                 chan->client_address = *client_ss;
2563
2564                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2565                         TALLOC_FREE(chan);
2566                         return false;
2567                 }
2568                 chan->binding_handle = chan->cli_pipe->binding_handle;
2569
2570                 DLIST_ADD(back_channels, chan);
2571
2572                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2573                                    receive_notify2_message_list);
2574                 /* Tell the connections db we're now interested in printer
2575                  * notify messages. */
2576                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2577                                             true, FLAG_MSG_PRINT_NOTIFY);
2578         }
2579
2580         /*
2581          * Tell the specific printing tdb we want messages for this printer
2582          * by registering our PID.
2583          */
2584
2585         if (!print_notify_register_pid(snum)) {
2586                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2587                           printer));
2588         }
2589
2590         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2591                                                  talloc_tos(),
2592                                                  printer,
2593                                                  localprinter,
2594                                                  type,
2595                                                  0,
2596                                                  NULL,
2597                                                  handle,
2598                                                  &result);
2599         if (!NT_STATUS_IS_OK(status)) {
2600                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2601                 result = ntstatus_to_werror(status);
2602         } else if (!W_ERROR_IS_OK(result)) {
2603                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2604         }
2605
2606         chan->active_connections++;
2607         *_chan = chan;
2608
2609         return (W_ERROR_IS_OK(result));
2610 }
2611
2612 /****************************************************************
2613  ****************************************************************/
2614
2615 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2616                                                              const struct spoolss_NotifyOption *r)
2617 {
2618         struct spoolss_NotifyOption *option;
2619         uint32_t i,k;
2620
2621         if (!r) {
2622                 return NULL;
2623         }
2624
2625         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2626         if (!option) {
2627                 return NULL;
2628         }
2629
2630         *option = *r;
2631
2632         if (!option->count) {
2633                 return option;
2634         }
2635
2636         option->types = talloc_zero_array(option,
2637                 struct spoolss_NotifyOptionType, option->count);
2638         if (!option->types) {
2639                 talloc_free(option);
2640                 return NULL;
2641         }
2642
2643         for (i=0; i < option->count; i++) {
2644                 option->types[i] = r->types[i];
2645
2646                 if (option->types[i].count) {
2647                         option->types[i].fields = talloc_zero_array(option,
2648                                 union spoolss_Field, option->types[i].count);
2649                         if (!option->types[i].fields) {
2650                                 talloc_free(option);
2651                                 return NULL;
2652                         }
2653                         for (k=0; k<option->types[i].count; k++) {
2654                                 option->types[i].fields[k] =
2655                                         r->types[i].fields[k];
2656                         }
2657                 }
2658         }
2659
2660         return option;
2661 }
2662
2663 /****************************************************************
2664  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2665  *
2666  * before replying OK: status=0 a rpc call is made to the workstation
2667  * asking ReplyOpenPrinter
2668  *
2669  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2670  * called from api_spoolss_rffpcnex
2671 ****************************************************************/
2672
2673 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2674                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2675 {
2676         int snum = -1;
2677         struct spoolss_NotifyOption *option = r->in.notify_options;
2678         struct sockaddr_storage client_ss;
2679
2680         /* store the notify value in the printer struct */
2681
2682         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2683
2684         if (!Printer) {
2685                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2686                         "Invalid handle (%s:%u:%u).\n",
2687                         OUR_HANDLE(r->in.handle)));
2688                 return WERR_BADFID;
2689         }
2690
2691         Printer->notify.flags           = r->in.flags;
2692         Printer->notify.options         = r->in.options;
2693         Printer->notify.printerlocal    = r->in.printer_local;
2694         Printer->notify.msg_ctx         = p->msg_ctx;
2695
2696         TALLOC_FREE(Printer->notify.option);
2697         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2698
2699         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2700
2701         /* Connect to the client machine and send a ReplyOpenPrinter */
2702
2703         if ( Printer->printer_type == SPLHND_SERVER)
2704                 snum = -1;
2705         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2706                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2707                 return WERR_BADFID;
2708
2709         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2710                 "client_address is %s\n", p->client_id->addr));
2711
2712         if (!lp_print_notify_backchannel(snum)) {
2713                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714                         "backchannel disabled\n"));
2715                 return WERR_SERVER_UNAVAILABLE;
2716         }
2717
2718         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2719                                    AI_NUMERICHOST)) {
2720                 return WERR_SERVER_UNAVAILABLE;
2721         }
2722
2723         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2724                                         Printer->notify.printerlocal, REG_SZ,
2725                                         &Printer->notify.cli_hnd,
2726                                         &Printer->notify.cli_chan,
2727                                         &client_ss, p->msg_ctx)) {
2728                 return WERR_SERVER_UNAVAILABLE;
2729         }
2730
2731         return WERR_OK;
2732 }
2733
2734 /*******************************************************************
2735  * fill a notify_info_data with the servername
2736  ********************************************************************/
2737
2738 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2739                                        int snum,
2740                                        struct spoolss_Notify *data,
2741                                        print_queue_struct *queue,
2742                                        struct spoolss_PrinterInfo2 *pinfo2,
2743                                        TALLOC_CTX *mem_ctx)
2744 {
2745         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2746 }
2747
2748 /*******************************************************************
2749  * fill a notify_info_data with the printername (not including the servername).
2750  ********************************************************************/
2751
2752 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2753                                         int snum,
2754                                         struct spoolss_Notify *data,
2755                                         print_queue_struct *queue,
2756                                         struct spoolss_PrinterInfo2 *pinfo2,
2757                                         TALLOC_CTX *mem_ctx)
2758 {
2759         /* the notify name should not contain the \\server\ part */
2760         const char *p = strrchr(pinfo2->printername, '\\');
2761
2762         if (!p) {
2763                 p = pinfo2->printername;
2764         } else {
2765                 p++;
2766         }
2767
2768         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2769 }
2770
2771 /*******************************************************************
2772  * fill a notify_info_data with the servicename
2773  ********************************************************************/
2774
2775 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2776                                       int snum,
2777                                       struct spoolss_Notify *data,
2778                                       print_queue_struct *queue,
2779                                       struct spoolss_PrinterInfo2 *pinfo2,
2780                                       TALLOC_CTX *mem_ctx)
2781 {
2782         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2783 }
2784
2785 /*******************************************************************
2786  * fill a notify_info_data with the port name
2787  ********************************************************************/
2788
2789 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2790                                      int snum,
2791                                      struct spoolss_Notify *data,
2792                                      print_queue_struct *queue,
2793                                      struct spoolss_PrinterInfo2 *pinfo2,
2794                                      TALLOC_CTX *mem_ctx)
2795 {
2796         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2797 }
2798
2799 /*******************************************************************
2800  * fill a notify_info_data with the printername
2801  * but it doesn't exist, have to see what to do
2802  ********************************************************************/
2803
2804 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2805                                        int snum,
2806                                        struct spoolss_Notify *data,
2807                                        print_queue_struct *queue,
2808                                        struct spoolss_PrinterInfo2 *pinfo2,
2809                                        TALLOC_CTX *mem_ctx)
2810 {
2811         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2812 }
2813
2814 /*******************************************************************
2815  * fill a notify_info_data with the comment
2816  ********************************************************************/
2817
2818 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2819                                    int snum,
2820                                    struct spoolss_Notify *data,
2821                                    print_queue_struct *queue,
2822                                    struct spoolss_PrinterInfo2 *pinfo2,
2823                                    TALLOC_CTX *mem_ctx)
2824 {
2825         const char *p;
2826
2827         if (*pinfo2->comment == '\0') {
2828                 p = lp_comment(snum);
2829         } else {
2830                 p = pinfo2->comment;
2831         }
2832
2833         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2834 }
2835
2836 /*******************************************************************
2837  * fill a notify_info_data with the comment
2838  * location = "Room 1, floor 2, building 3"
2839  ********************************************************************/
2840
2841 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2842                                     int snum,
2843                                     struct spoolss_Notify *data,
2844                                     print_queue_struct *queue,
2845                                     struct spoolss_PrinterInfo2 *pinfo2,
2846                                     TALLOC_CTX *mem_ctx)
2847 {
2848         const char *loc = pinfo2->location;
2849         NTSTATUS status;
2850
2851         status = printer_list_get_printer(mem_ctx,
2852                                           pinfo2->sharename,
2853                                           NULL,
2854                                           &loc,
2855                                           NULL);
2856         if (NT_STATUS_IS_OK(status)) {
2857                 if (loc == NULL) {
2858                         loc = pinfo2->location;
2859                 }
2860         }
2861
2862         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2863 }
2864
2865 /*******************************************************************
2866  * fill a notify_info_data with the device mode
2867  * jfm:xxxx don't to it for know but that's a real problem !!!
2868  ********************************************************************/
2869
2870 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2871                                    int snum,
2872                                    struct spoolss_Notify *data,
2873                                    print_queue_struct *queue,
2874                                    struct spoolss_PrinterInfo2 *pinfo2,
2875                                    TALLOC_CTX *mem_ctx)
2876 {
2877         /* for a dummy implementation we have to zero the fields */
2878         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with the separator file name
2883  ********************************************************************/
2884
2885 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2886                                    int snum,
2887                                    struct spoolss_Notify *data,
2888                                    print_queue_struct *queue,
2889                                    struct spoolss_PrinterInfo2 *pinfo2,
2890                                    TALLOC_CTX *mem_ctx)
2891 {
2892         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2893 }
2894
2895 /*******************************************************************
2896  * fill a notify_info_data with the print processor
2897  * jfm:xxxx return always winprint to indicate we don't do anything to it
2898  ********************************************************************/
2899
2900 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2901                                            int snum,
2902                                            struct spoolss_Notify *data,
2903                                            print_queue_struct *queue,
2904                                            struct spoolss_PrinterInfo2 *pinfo2,
2905                                            TALLOC_CTX *mem_ctx)
2906 {
2907         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2908 }
2909
2910 /*******************************************************************
2911  * fill a notify_info_data with the print processor options
2912  * jfm:xxxx send an empty string
2913  ********************************************************************/
2914
2915 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2916                                       int snum,
2917                                       struct spoolss_Notify *data,
2918                                       print_queue_struct *queue,
2919                                       struct spoolss_PrinterInfo2 *pinfo2,
2920                                       TALLOC_CTX *mem_ctx)
2921 {
2922         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2923 }
2924
2925 /*******************************************************************
2926  * fill a notify_info_data with the data type
2927  * jfm:xxxx always send RAW as data type
2928  ********************************************************************/
2929
2930 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2931                                     int snum,
2932                                     struct spoolss_Notify *data,
2933                                     print_queue_struct *queue,
2934                                     struct spoolss_PrinterInfo2 *pinfo2,
2935                                     TALLOC_CTX *mem_ctx)
2936 {
2937         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2938 }
2939
2940 /*******************************************************************
2941  * fill a notify_info_data with the security descriptor
2942  * jfm:xxxx send an null pointer to say no security desc
2943  * have to implement security before !
2944  ********************************************************************/
2945
2946 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2947                                          int snum,
2948                                          struct spoolss_Notify *data,
2949                                          print_queue_struct *queue,
2950                                          struct spoolss_PrinterInfo2 *pinfo2,
2951                                          TALLOC_CTX *mem_ctx)
2952 {
2953         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2954 }
2955
2956 /*******************************************************************
2957  * fill a notify_info_data with the attributes
2958  * jfm:xxxx a samba printer is always shared
2959  ********************************************************************/
2960
2961 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2962                                       int snum,
2963                                       struct spoolss_Notify *data,
2964                                       print_queue_struct *queue,
2965                                       struct spoolss_PrinterInfo2 *pinfo2,
2966                                       TALLOC_CTX *mem_ctx)
2967 {
2968         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2969 }
2970
2971 /*******************************************************************
2972  * fill a notify_info_data with the priority
2973  ********************************************************************/
2974
2975 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2976                                     int snum,
2977                                     struct spoolss_Notify *data,
2978                                     print_queue_struct *queue,
2979                                     struct spoolss_PrinterInfo2 *pinfo2,
2980                                     TALLOC_CTX *mem_ctx)
2981 {
2982         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2983 }
2984
2985 /*******************************************************************
2986  * fill a notify_info_data with the default priority
2987  ********************************************************************/
2988
2989 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2990                                             int snum,
2991                                             struct spoolss_Notify *data,
2992                                             print_queue_struct *queue,
2993                                             struct spoolss_PrinterInfo2 *pinfo2,
2994                                             TALLOC_CTX *mem_ctx)
2995 {
2996         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2997 }
2998
2999 /*******************************************************************
3000  * fill a notify_info_data with the start time
3001  ********************************************************************/
3002
3003 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3004                                       int snum,
3005                                       struct spoolss_Notify *data,
3006                                       print_queue_struct *queue,
3007                                       struct spoolss_PrinterInfo2 *pinfo2,
3008                                       TALLOC_CTX *mem_ctx)
3009 {
3010         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3011 }
3012
3013 /*******************************************************************
3014  * fill a notify_info_data with the until time
3015  ********************************************************************/
3016
3017 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3018                                       int snum,
3019                                       struct spoolss_Notify *data,
3020                                       print_queue_struct *queue,
3021                                       struct spoolss_PrinterInfo2 *pinfo2,
3022                                       TALLOC_CTX *mem_ctx)
3023 {
3024         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3025 }
3026
3027 /*******************************************************************
3028  * fill a notify_info_data with the status
3029  ********************************************************************/
3030
3031 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3032                                   int snum,
3033                                   struct spoolss_Notify *data,
3034                                   print_queue_struct *queue,
3035                                   struct spoolss_PrinterInfo2 *pinfo2,
3036                                   TALLOC_CTX *mem_ctx)
3037 {
3038         print_status_struct status;
3039
3040         print_queue_length(msg_ctx, snum, &status);
3041         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3042 }
3043
3044 /*******************************************************************
3045  * fill a notify_info_data with the number of jobs queued
3046  ********************************************************************/
3047
3048 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3049                                  int snum,
3050                                  struct spoolss_Notify *data,
3051                                  print_queue_struct *queue,
3052                                  struct spoolss_PrinterInfo2 *pinfo2,
3053                                  TALLOC_CTX *mem_ctx)
3054 {
3055         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3056                 data, print_queue_length(msg_ctx, snum, NULL));
3057 }
3058
3059 /*******************************************************************
3060  * fill a notify_info_data with the average ppm
3061  ********************************************************************/
3062
3063 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3064                                        int snum,
3065                                        struct spoolss_Notify *data,
3066                                        print_queue_struct *queue,
3067                                        struct spoolss_PrinterInfo2 *pinfo2,
3068                                        TALLOC_CTX *mem_ctx)
3069 {
3070         /* always respond 8 pages per minutes */
3071         /* a little hard ! */
3072         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3073 }
3074
3075 /*******************************************************************
3076  * fill a notify_info_data with username
3077  ********************************************************************/
3078
3079 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3080                                     int snum,
3081                                     struct spoolss_Notify *data,
3082                                     print_queue_struct *queue,
3083                                     struct spoolss_PrinterInfo2 *pinfo2,
3084                                     TALLOC_CTX *mem_ctx)
3085 {
3086         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3087 }
3088
3089 /*******************************************************************
3090  * fill a notify_info_data with job status
3091  ********************************************************************/
3092
3093 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3094                                       int snum,
3095                                       struct spoolss_Notify *data,
3096                                       print_queue_struct *queue,
3097                                       struct spoolss_PrinterInfo2 *pinfo2,
3098                                       TALLOC_CTX *mem_ctx)
3099 {
3100         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3101 }
3102
3103 /*******************************************************************
3104  * fill a notify_info_data with job name
3105  ********************************************************************/
3106
3107 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3108                                     int snum,
3109                                     struct spoolss_Notify *data,
3110                                     print_queue_struct *queue,
3111                                     struct spoolss_PrinterInfo2 *pinfo2,
3112                                     TALLOC_CTX *mem_ctx)
3113 {
3114         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3115 }
3116
3117 /*******************************************************************
3118  * fill a notify_info_data with job status
3119  ********************************************************************/
3120
3121 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3122                                              int snum,
3123                                              struct spoolss_Notify *data,
3124                                              print_queue_struct *queue,
3125                                              struct spoolss_PrinterInfo2 *pinfo2,
3126                                              TALLOC_CTX *mem_ctx)
3127 {
3128         /*
3129          * Now we're returning job status codes we just return a "" here. JRA.
3130          */
3131
3132         const char *p = "";
3133
3134 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3135         p = "unknown";
3136
3137         switch (queue->status) {
3138         case LPQ_QUEUED:
3139                 p = "Queued";
3140                 break;
3141         case LPQ_PAUSED:
3142                 p = "";    /* NT provides the paused string */
3143                 break;
3144         case LPQ_SPOOLING:
3145                 p = "Spooling";
3146                 break;
3147         case LPQ_PRINTING:
3148                 p = "Printing";
3149                 break;
3150         }
3151 #endif /* NO LONGER NEEDED. */
3152
3153         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3154 }
3155
3156 /*******************************************************************
3157  * fill a notify_info_data with job time
3158  ********************************************************************/
3159
3160 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3161                                     int snum,
3162                                     struct spoolss_Notify *data,
3163                                     print_queue_struct *queue,
3164                                     struct spoolss_PrinterInfo2 *pinfo2,
3165                                     TALLOC_CTX *mem_ctx)
3166 {
3167         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3168 }
3169
3170 /*******************************************************************
3171  * fill a notify_info_data with job size
3172  ********************************************************************/
3173
3174 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3175                                     int snum,
3176                                     struct spoolss_Notify *data,
3177                                     print_queue_struct *queue,
3178                                     struct spoolss_PrinterInfo2 *pinfo2,
3179                                     TALLOC_CTX *mem_ctx)
3180 {
3181         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3182 }
3183
3184 /*******************************************************************
3185  * fill a notify_info_data with page info
3186  ********************************************************************/
3187 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3188                                        int snum,
3189                                 struct spoolss_Notify *data,
3190                                 print_queue_struct *queue,
3191                                 struct spoolss_PrinterInfo2 *pinfo2,
3192                                 TALLOC_CTX *mem_ctx)
3193 {
3194         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3195 }
3196
3197 /*******************************************************************
3198  * fill a notify_info_data with pages printed info.
3199  ********************************************************************/
3200 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3201                                          int snum,
3202                                 struct spoolss_Notify *data,
3203                                 print_queue_struct *queue,
3204                                 struct spoolss_PrinterInfo2 *pinfo2,
3205                                 TALLOC_CTX *mem_ctx)
3206 {
3207         /* Add code when back-end tracks this */
3208         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3209 }
3210
3211 /*******************************************************************
3212  Fill a notify_info_data with job position.
3213  ********************************************************************/
3214
3215 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3216                                         int snum,
3217                                         struct spoolss_Notify *data,
3218                                         print_queue_struct *queue,
3219                                         struct spoolss_PrinterInfo2 *pinfo2,
3220                                         TALLOC_CTX *mem_ctx)
3221 {
3222         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3223 }
3224
3225 /*******************************************************************
3226  Fill a notify_info_data with submitted time.
3227  ********************************************************************/
3228
3229 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3230                                           int snum,
3231                                           struct spoolss_Notify *data,
3232                                           print_queue_struct *queue,
3233                                           struct spoolss_PrinterInfo2 *pinfo2,
3234                                           TALLOC_CTX *mem_ctx)
3235 {
3236         data->data.string.string = NULL;
3237         data->data.string.size = 0;
3238
3239         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3240                                &data->data.string.string,
3241                                &data->data.string.size);
3242
3243 }
3244
3245 struct s_notify_info_data_table
3246 {
3247         enum spoolss_NotifyType type;
3248         uint16_t field;
3249         const char *name;
3250         enum spoolss_NotifyTable variable_type;
3251         void (*fn) (struct messaging_context *msg_ctx,
3252                     int snum, struct spoolss_Notify *data,
3253                     print_queue_struct *queue,
3254                     struct spoolss_PrinterInfo2 *pinfo2,
3255                     TALLOC_CTX *mem_ctx);
3256 };
3257
3258 /* A table describing the various print notification constants and
3259    whether the notification data is a pointer to a variable sized
3260    buffer, a one value uint32_t or a two value uint32_t. */
3261
3262 static const struct s_notify_info_data_table notify_info_data_table[] =
3263 {
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3313 };
3314
3315 /*******************************************************************
3316  Return the variable_type of info_data structure.
3317 ********************************************************************/
3318
3319 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3320                                                                   uint16_t field)
3321 {
3322         int i=0;
3323
3324         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3325                 if ( (notify_info_data_table[i].type == type) &&
3326                      (notify_info_data_table[i].field == field) ) {
3327                         return notify_info_data_table[i].variable_type;
3328                 }
3329         }
3330
3331         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3332
3333         return (enum spoolss_NotifyTable) 0;
3334 }
3335
3336 /****************************************************************************
3337 ****************************************************************************/
3338
3339 static bool search_notify(enum spoolss_NotifyType type,
3340                           uint16_t field,
3341                           int *value)
3342 {
3343         int i;
3344
3345         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3346                 if (notify_info_data_table[i].type == type &&
3347                     notify_info_data_table[i].field == field &&
3348                     notify_info_data_table[i].fn != NULL) {
3349                         *value = i;
3350                         return true;
3351                 }
3352         }
3353
3354         return false;
3355 }
3356
3357 /****************************************************************************
3358 ****************************************************************************/
3359
3360 static void construct_info_data(struct spoolss_Notify *info_data,
3361                                 enum spoolss_NotifyType type,
3362                                 uint16_t field, int id)
3363 {
3364         info_data->type                 = type;
3365         info_data->field.field          = field;
3366         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3367         info_data->job_id               = id;
3368 }
3369
3370 /*******************************************************************
3371  *
3372  * fill a notify_info struct with info asked
3373  *
3374  ********************************************************************/
3375
3376 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3377                                           struct printer_handle *print_hnd,
3378                                           struct spoolss_NotifyInfo *info,
3379                                           struct spoolss_PrinterInfo2 *pinfo2,
3380                                           int snum,
3381                                           const struct spoolss_NotifyOptionType *option_type,
3382                                           uint32_t id,
3383                                           TALLOC_CTX *mem_ctx)
3384 {
3385         int field_num,j;
3386         enum spoolss_NotifyType type;
3387         uint16_t field;
3388
3389         struct spoolss_Notify *current_data;
3390
3391         type = option_type->type;
3392
3393         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3394                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3395                 option_type->count, lp_servicename(snum)));
3396
3397         for(field_num=0; field_num < option_type->count; field_num++) {
3398                 field = option_type->fields[field_num].field;
3399
3400                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3401
3402                 if (!search_notify(type, field, &j) )
3403                         continue;
3404
3405                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3406                                                       struct spoolss_Notify,
3407                                                       info->count + 1);
3408                 if (info->notifies == NULL) {
3409                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3410                         return false;
3411                 }
3412
3413                 current_data = &info->notifies[info->count];
3414
3415                 construct_info_data(current_data, type, field, id);
3416
3417                 DEBUG(10, ("construct_notify_printer_info: "
3418                            "calling [%s]  snum=%d  printername=[%s])\n",
3419                            notify_info_data_table[j].name, snum,
3420                            pinfo2->printername));
3421
3422                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3423                                              NULL, pinfo2, mem_ctx);
3424
3425                 info->count++;
3426         }
3427
3428         return true;
3429 }
3430
3431 /*******************************************************************
3432  *
3433  * fill a notify_info struct with info asked
3434  *
3435  ********************************************************************/
3436
3437 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3438                                        print_queue_struct *queue,
3439                                        struct spoolss_NotifyInfo *info,
3440                                        struct spoolss_PrinterInfo2 *pinfo2,
3441                                        int snum,
3442                                        const struct spoolss_NotifyOptionType *option_type,
3443                                        uint32_t id,
3444                                        TALLOC_CTX *mem_ctx)
3445 {
3446         int field_num,j;
3447         enum spoolss_NotifyType type;
3448         uint16_t field;
3449         struct spoolss_Notify *current_data;
3450
3451         DEBUG(4,("construct_notify_jobs_info\n"));
3452
3453         type = option_type->type;
3454
3455         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3456                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3457                 option_type->count));
3458
3459         for(field_num=0; field_num<option_type->count; field_num++) {
3460                 field = option_type->fields[field_num].field;
3461
3462                 if (!search_notify(type, field, &j) )
3463                         continue;
3464
3465                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3466                                                       struct spoolss_Notify,
3467                                                       info->count + 1);
3468                 if (info->notifies == NULL) {
3469                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3470                         return false;
3471                 }
3472
3473                 current_data=&(info->notifies[info->count]);
3474
3475                 construct_info_data(current_data, type, field, id);
3476                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3477                                              queue, pinfo2, mem_ctx);
3478                 info->count++;
3479         }
3480
3481         return true;
3482 }
3483
3484 /*
3485  * JFM: The enumeration is not that simple, it's even non obvious.
3486  *
3487  * let's take an example: I want to monitor the PRINTER SERVER for
3488  * the printer's name and the number of jobs currently queued.
3489  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3490  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3491  *
3492  * I have 3 printers on the back of my server.
3493  *
3494  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3495  * structures.
3496  *   Number     Data                    Id
3497  *      1       printer 1 name          1
3498  *      2       printer 1 cjob          1
3499  *      3       printer 2 name          2
3500  *      4       printer 2 cjob          2
3501  *      5       printer 3 name          3
3502  *      6       printer 3 name          3
3503  *
3504  * that's the print server case, the printer case is even worse.
3505  */
3506
3507 /*******************************************************************
3508  *
3509  * enumerate all printers on the printserver
3510  * fill a notify_info struct with info asked
3511  *
3512  ********************************************************************/
3513
3514 static WERROR printserver_notify_info(struct pipes_struct *p,
3515                                       struct policy_handle *hnd,
3516                                       struct spoolss_NotifyInfo *info,
3517                                       TALLOC_CTX *mem_ctx)
3518 {
3519         int snum;
3520         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3521         int n_services=lp_numservices();
3522         int i;
3523         struct spoolss_NotifyOption *option;
3524         struct spoolss_NotifyOptionType option_type;
3525         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3526         WERROR result;
3527
3528         DEBUG(4,("printserver_notify_info\n"));
3529
3530         if (!Printer)
3531                 return WERR_BADFID;
3532
3533         option = Printer->notify.option;
3534
3535         info->version   = 2;
3536         info->notifies  = NULL;
3537         info->count     = 0;
3538
3539         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3540            sending a ffpcn() request first */
3541
3542         if ( !option )
3543                 return WERR_BADFID;
3544
3545         for (i=0; i<option->count; i++) {
3546                 option_type = option->types[i];
3547
3548                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3549                         continue;
3550
3551                 for (snum = 0; snum < n_services; snum++) {
3552                         if (!lp_browseable(snum) ||
3553                             !lp_snum_ok(snum) ||
3554                             !lp_print_ok(snum)) {
3555                                 continue; /* skip */
3556                         }
3557
3558                         /* Maybe we should use the SYSTEM session_info here... */
3559                         result = winreg_get_printer_internal(mem_ctx,
3560                                                     get_session_info_system(),
3561                                                     p->msg_ctx,
3562                                                     lp_servicename(snum),
3563                                                     &pinfo2);
3564                         if (!W_ERROR_IS_OK(result)) {
3565                                 DEBUG(4, ("printserver_notify_info: "
3566                                           "Failed to get printer [%s]\n",
3567                                           lp_servicename(snum)));
3568                                 continue;
3569                         }
3570
3571
3572                         construct_notify_printer_info(p->msg_ctx,
3573                                                       Printer, info,
3574                                                       pinfo2, snum,
3575                                                       &option_type, snum,
3576                                                       mem_ctx);
3577
3578                         TALLOC_FREE(pinfo2);
3579                 }
3580         }
3581
3582 #if 0
3583         /*
3584          * Debugging information, don't delete.
3585          */
3586
3587         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3588         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3589         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3590
3591         for (i=0; i<info->count; i++) {
3592                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3593                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3594                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3595         }
3596 #endif
3597
3598         return WERR_OK;
3599 }
3600
3601 /*******************************************************************
3602  *
3603  * fill a notify_info struct with info asked
3604  *
3605  ********************************************************************/
3606
3607 static WERROR printer_notify_info(struct pipes_struct *p,
3608                                   struct policy_handle *hnd,
3609                                   struct spoolss_NotifyInfo *info,
3610                                   TALLOC_CTX *mem_ctx)
3611 {
3612         int snum;
3613         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3614         int i;
3615         uint32_t id;
3616         struct spoolss_NotifyOption *option;
3617         struct spoolss_NotifyOptionType option_type;
3618         int count,j;
3619         print_queue_struct *queue=NULL;
3620         print_status_struct status;
3621         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3622         WERROR result;
3623
3624         DEBUG(4,("printer_notify_info\n"));
3625
3626         if (!Printer)
3627                 return WERR_BADFID;
3628
3629         option = Printer->notify.option;
3630         id = 0x0;
3631
3632         info->version   = 2;
3633         info->notifies  = NULL;
3634         info->count     = 0;
3635
3636         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3637            sending a ffpcn() request first */
3638
3639         if ( !option )
3640                 return WERR_BADFID;
3641
3642         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3643                 return WERR_BADFID;
3644         }
3645
3646         /* Maybe we should use the SYSTEM session_info here... */
3647         result = winreg_get_printer_internal(mem_ctx,
3648                                     get_session_info_system(),
3649                                     p->msg_ctx,
3650                                     lp_servicename(snum), &pinfo2);
3651         if (!W_ERROR_IS_OK(result)) {
3652                 return WERR_BADFID;
3653         }
3654
3655         /*
3656          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3657          * correct servername.
3658          */
3659         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3660         if (pinfo2->servername == NULL) {
3661                 return WERR_NOMEM;
3662         }
3663
3664         for (i=0; i<option->count; i++) {
3665                 option_type = option->types[i];
3666
3667                 switch (option_type.type) {
3668                 case PRINTER_NOTIFY_TYPE:
3669                         if (construct_notify_printer_info(p->msg_ctx,
3670                                                           Printer, info,
3671                                                           pinfo2, snum,
3672                                                           &option_type, id,
3673                                                           mem_ctx)) {
3674                                 id--;
3675                         }
3676                         break;
3677
3678                 case JOB_NOTIFY_TYPE:
3679
3680                         count = print_queue_status(p->msg_ctx, snum, &queue,
3681                                                    &status);
3682
3683                         for (j=0; j<count; j++) {
3684                                 construct_notify_jobs_info(p->msg_ctx,
3685                                                            &queue[j], info,
3686                                                            pinfo2, snum,
3687                                                            &option_type,
3688                                                            queue[j].job,
3689                                                            mem_ctx);
3690                         }
3691
3692                         SAFE_FREE(queue);
3693                         break;
3694                 }
3695         }
3696
3697         /*
3698          * Debugging information, don't delete.
3699          */
3700         /*
3701         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3703         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3704
3705         for (i=0; i<info->count; i++) {
3706                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3708                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3709         }
3710         */
3711
3712         talloc_free(pinfo2);
3713         return WERR_OK;
3714 }
3715
3716 /****************************************************************
3717  _spoolss_RouterRefreshPrinterChangeNotify
3718 ****************************************************************/
3719
3720 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3721                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3722 {
3723         struct spoolss_NotifyInfo *info;
3724
3725         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3726         WERROR result = WERR_BADFID;
3727
3728         /* we always have a spoolss_NotifyInfo struct */
3729         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3730         if (!info) {
3731                 result = WERR_NOMEM;
3732                 goto done;
3733         }
3734
3735         *r->out.info = info;
3736
3737         if (!Printer) {
3738                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3739                         "Invalid handle (%s:%u:%u).\n",
3740                         OUR_HANDLE(r->in.handle)));
3741                 goto done;
3742         }
3743
3744         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3745
3746         /*
3747          *      We are now using the change value, and
3748          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3749          *      I don't have a global notification system, I'm sending back all the
3750          *      information even when _NOTHING_ has changed.
3751          */
3752
3753         /* We need to keep track of the change value to send back in
3754            RRPCN replies otherwise our updates are ignored. */
3755
3756         Printer->notify.fnpcn = true;
3757
3758         if (Printer->notify.cli_chan != NULL &&
3759             Printer->notify.cli_chan->active_connections > 0) {
3760                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761                         "Saving change value in request [%x]\n",
3762                         r->in.change_low));
3763                 Printer->notify.change = r->in.change_low;
3764         }
3765
3766         /* just ignore the spoolss_NotifyOption */
3767
3768         switch (Printer->printer_type) {
3769                 case SPLHND_SERVER:
3770                         result = printserver_notify_info(p, r->in.handle,
3771                                                          info, p->mem_ctx);
3772                         break;
3773
3774                 case SPLHND_PRINTER:
3775                         result = printer_notify_info(p, r->in.handle,
3776                                                      info, p->mem_ctx);
3777                         break;
3778         }
3779
3780         Printer->notify.fnpcn = false;
3781
3782 done:
3783         return result;
3784 }
3785
3786 /********************************************************************
3787  ********************************************************************/
3788
3789 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3790                                  const char *servername,
3791                                  const char *printername,
3792                                  const char **printername_p)
3793 {
3794         /* FIXME: add lp_force_printername() */
3795
3796         if (servername == NULL) {
3797                 *printername_p = talloc_strdup(mem_ctx, printername);
3798                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3799                 return WERR_OK;
3800         }
3801
3802         if (servername[0] == '\\' && servername[1] == '\\') {
3803                 servername += 2;
3804         }
3805
3806         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3807         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3808
3809         return WERR_OK;
3810 }
3811
3812 /********************************************************************
3813  ********************************************************************/
3814
3815 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3816                                           const char *printername)
3817 {
3818         if (dm == NULL) {
3819                 return;
3820         }
3821
3822         dm->devicename = talloc_strndup(dm, printername,
3823                                         MIN(strlen(printername), 31));
3824 }
3825
3826 /********************************************************************
3827  * construct_printer_info_0
3828  * fill a printer_info_0 struct
3829  ********************************************************************/
3830
3831 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3832                                       const struct auth_serversupplied_info *session_info,
3833                                       struct messaging_context *msg_ctx,
3834                                       struct spoolss_PrinterInfo2 *info2,
3835                                       const char *servername,
3836                                       struct spoolss_PrinterInfo0 *r,
3837                                       int snum)
3838 {
3839         int count;
3840         struct printer_session_counter *session_counter;
3841         struct timeval setuptime;
3842         print_status_struct status;
3843         WERROR result;
3844
3845         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3846         if (!W_ERROR_IS_OK(result)) {
3847                 return result;
3848         }
3849
3850         if (servername) {
3851                 r->servername = talloc_strdup(mem_ctx, servername);
3852                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3853         } else {
3854                 r->servername = NULL;
3855         }
3856
3857         count = print_queue_length(msg_ctx, snum, &status);
3858
3859         /* check if we already have a counter for this printer */
3860         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3861                 if (session_counter->snum == snum)
3862                         break;
3863         }
3864
3865         /* it's the first time, add it to the list */
3866         if (session_counter == NULL) {
3867                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3868                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3869                 session_counter->snum           = snum;
3870                 session_counter->counter        = 0;
3871                 DLIST_ADD(counter_list, session_counter);
3872         }
3873
3874         /* increment it */
3875         session_counter->counter++;
3876
3877         r->cjobs                        = count;
3878         r->total_jobs                   = 0;
3879         r->total_bytes                  = 0;
3880
3881         get_startup_time(&setuptime);
3882         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3883
3884         /* JFM:
3885          * the global_counter should be stored in a TDB as it's common to all the clients
3886          * and should be zeroed on samba startup
3887          */
3888         r->global_counter               = session_counter->counter;
3889         r->total_pages                  = 0;
3890         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3891         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3892         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3893         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3894         r->spooling                     = 0;
3895         r->max_spooling                 = 0;
3896         r->session_counter              = session_counter->counter;
3897         r->num_error_out_of_paper       = 0x0;
3898         r->num_error_not_ready          = 0x0;          /* number of print failure */
3899         r->job_error                    = 0x0;
3900         r->number_of_processors         = 0x1;
3901         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3902         r->high_part_total_bytes        = 0x0;
3903
3904         /* ChangeID in milliseconds*/
3905         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3906                                     info2->sharename, &r->change_id);
3907
3908         r->last_error                   = WERR_OK;
3909         r->status                       = nt_printq_status(status.status);
3910         r->enumerate_network_printers   = 0x0;
3911         r->c_setprinter                 = 0x0;
3912         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3913         r->processor_level              = 0x6;          /* 6  ???*/
3914         r->ref_ic                       = 0;
3915         r->reserved2                    = 0;
3916         r->reserved3                    = 0;
3917
3918         return WERR_OK;
3919 }
3920
3921
3922 /********************************************************************
3923  * construct_printer_info1
3924  * fill a spoolss_PrinterInfo1 struct
3925 ********************************************************************/
3926
3927 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3928                                       const struct spoolss_PrinterInfo2 *info2,
3929                                       uint32_t flags,
3930                                       const char *servername,
3931                                       struct spoolss_PrinterInfo1 *r,
3932                                       int snum)
3933 {
3934         WERROR result;
3935
3936         r->flags                = flags;
3937
3938         if (info2->comment == NULL || info2->comment[0] == '\0') {
3939                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3940         } else {
3941                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3942         }
3943         W_ERROR_HAVE_NO_MEMORY(r->comment);
3944
3945         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3946         if (!W_ERROR_IS_OK(result)) {
3947                 return result;
3948         }
3949
3950         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3951                                                   r->name,
3952                                                   info2->drivername,
3953                                                   r->comment);
3954         W_ERROR_HAVE_NO_MEMORY(r->description);
3955
3956         return WERR_OK;
3957 }
3958
3959 /********************************************************************
3960  * construct_printer_info2
3961  * fill a spoolss_PrinterInfo2 struct
3962 ********************************************************************/
3963
3964 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3965                                       struct messaging_context *msg_ctx,
3966                                       const struct spoolss_PrinterInfo2 *info2,
3967                                       const char *servername,
3968                                       struct spoolss_PrinterInfo2 *r,
3969                                       int snum)
3970 {
3971         int count;
3972         print_status_struct status;
3973         WERROR result;
3974
3975         count = print_queue_length(msg_ctx, snum, &status);
3976
3977         if (servername) {
3978                 r->servername           = talloc_strdup(mem_ctx, servername);
3979                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3980         } else {
3981                 r->servername           = NULL;
3982         }
3983
3984         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3985         if (!W_ERROR_IS_OK(result)) {
3986                 return result;
3987         }
3988
3989         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3990         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3991         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3992         W_ERROR_HAVE_NO_MEMORY(r->portname);
3993         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3994         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3995
3996         if (info2->comment[0] == '\0') {
3997                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3998         } else {
3999                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4000         }
4001         W_ERROR_HAVE_NO_MEMORY(r->comment);
4002
4003         r->location     = talloc_strdup(mem_ctx, info2->location);
4004         if (info2->location[0] == '\0') {
4005                 const char *loc = NULL;
4006                 NTSTATUS nt_status;
4007
4008                 nt_status = printer_list_get_printer(mem_ctx,
4009                                                      info2->sharename,
4010                                                      NULL,
4011                                                      &loc,
4012                                                      NULL);
4013                 if (NT_STATUS_IS_OK(nt_status)) {
4014                         if (loc != NULL) {
4015                                 r->location = talloc_strdup(mem_ctx, loc);
4016                         }
4017                 }
4018         }
4019         W_ERROR_HAVE_NO_MEMORY(r->location);
4020
4021         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4022         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4023         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4024         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4025         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4026         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4027         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4028         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4029
4030         r->attributes           = info2->attributes;
4031
4032         r->priority             = info2->priority;
4033         r->defaultpriority      = info2->defaultpriority;
4034         r->starttime            = info2->starttime;
4035         r->untiltime            = info2->untiltime;
4036         r->status               = nt_printq_status(status.status);
4037         r->cjobs                = count;
4038         r->averageppm           = info2->averageppm;
4039
4040         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4041         if (!r->devmode) {
4042                 DEBUG(8,("Returning NULL Devicemode!\n"));
4043         }
4044
4045         compose_devicemode_devicename(r->devmode, r->printername);
4046
4047         r->secdesc = NULL;
4048
4049         if (info2->secdesc != NULL) {
4050                 /* don't use talloc_steal() here unless you do a deep steal of all
4051                    the SEC_DESC members */
4052
4053                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4054         }
4055
4056         return WERR_OK;
4057 }
4058
4059 /********************************************************************
4060  * construct_printer_info3
4061  * fill a spoolss_PrinterInfo3 struct
4062  ********************************************************************/
4063
4064 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4065                                       const struct spoolss_PrinterInfo2 *info2,
4066                                       const char *servername,
4067                                       struct spoolss_PrinterInfo3 *r,
4068                                       int snum)
4069 {
4070         /* These are the components of the SD we are returning. */
4071
4072         if (info2->secdesc != NULL) {
4073                 /* don't use talloc_steal() here unless you do a deep steal of all
4074                    the SEC_DESC members */
4075
4076                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4077                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4078         }
4079
4080         return WERR_OK;
4081 }
4082
4083 /********************************************************************
4084  * construct_printer_info4
4085  * fill a spoolss_PrinterInfo4 struct
4086  ********************************************************************/
4087
4088 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4089                                       const struct spoolss_PrinterInfo2 *info2,
4090                                       const char *servername,
4091                                       struct spoolss_PrinterInfo4 *r,
4092                                       int snum)
4093 {
4094         WERROR result;
4095
4096         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4097         if (!W_ERROR_IS_OK(result)) {
4098                 return result;
4099         }
4100
4101         if (servername) {
4102                 r->servername   = talloc_strdup(mem_ctx, servername);
4103                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4104         } else {
4105                 r->servername = NULL;
4106         }
4107
4108         r->attributes   = info2->attributes;
4109
4110         return WERR_OK;
4111 }
4112
4113 /********************************************************************
4114  * construct_printer_info5
4115  * fill a spoolss_PrinterInfo5 struct
4116  ********************************************************************/
4117
4118 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4119                                       const struct spoolss_PrinterInfo2 *info2,
4120                                       const char *servername,
4121                                       struct spoolss_PrinterInfo5 *r,
4122                                       int snum)
4123 {
4124         WERROR result;
4125
4126         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4127         if (!W_ERROR_IS_OK(result)) {
4128                 return result;
4129         }
4130
4131         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4132         W_ERROR_HAVE_NO_MEMORY(r->portname);
4133
4134         r->attributes   = info2->attributes;
4135
4136         /* these two are not used by NT+ according to MSDN */
4137         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4138         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4139
4140         return WERR_OK;
4141 }
4142
4143 /********************************************************************
4144  * construct_printer_info_6
4145  * fill a spoolss_PrinterInfo6 struct
4146  ********************************************************************/
4147
4148 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4149                                       struct messaging_context *msg_ctx,
4150                                       const struct spoolss_PrinterInfo2 *info2,
4151                                       const char *servername,
4152                                       struct spoolss_PrinterInfo6 *r,
4153                                       int snum)
4154 {
4155         int count;
4156         print_status_struct status;
4157
4158         count = print_queue_length(msg_ctx, snum, &status);
4159
4160         r->status = nt_printq_status(status.status);
4161
4162         return WERR_OK;
4163 }
4164
4165 /********************************************************************
4166  * construct_printer_info7
4167  * fill a spoolss_PrinterInfo7 struct
4168  ********************************************************************/
4169
4170 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4171                                       struct messaging_context *msg_ctx,
4172                                       const char *servername,
4173                                       struct spoolss_PrinterInfo7 *r,
4174                                       int snum)
4175 {
4176         struct auth_serversupplied_info *session_info;
4177         struct GUID guid;
4178         NTSTATUS status;
4179
4180         status = make_session_info_system(mem_ctx, &session_info);
4181         if (!NT_STATUS_IS_OK(status)) {
4182                 DEBUG(0, ("construct_printer_info7: "
4183                           "Could not create system session_info\n"));
4184                 return WERR_NOMEM;
4185         }
4186
4187         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4188                                  servername,
4189                                  lp_servicename(snum), &guid, NULL)) {
4190                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4191                 r->action = DSPRINT_PUBLISH;
4192         } else {
4193                 r->guid = talloc_strdup(mem_ctx, "");
4194                 r->action = DSPRINT_UNPUBLISH;
4195         }
4196         W_ERROR_HAVE_NO_MEMORY(r->guid);
4197
4198         TALLOC_FREE(session_info);
4199         return WERR_OK;
4200 }
4201
4202 /********************************************************************
4203  * construct_printer_info8
4204  * fill a spoolss_PrinterInfo8 struct
4205  ********************************************************************/
4206
4207 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4208                                       const struct spoolss_PrinterInfo2 *info2,
4209                                       const char *servername,
4210                                       struct spoolss_DeviceModeInfo *r,
4211                                       int snum)
4212 {
4213         WERROR result;
4214         const char *printername;
4215
4216         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4217         if (!W_ERROR_IS_OK(result)) {
4218                 return result;
4219         }
4220
4221         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4222         if (!r->devmode) {
4223                 DEBUG(8,("Returning NULL Devicemode!\n"));
4224         }
4225
4226         compose_devicemode_devicename(r->devmode, printername);
4227
4228         return WERR_OK;
4229 }
4230
4231
4232 /********************************************************************
4233 ********************************************************************/
4234
4235 static bool snum_is_shared_printer(int snum)
4236 {
4237         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4238 }
4239
4240 /********************************************************************
4241  Spoolss_enumprinters.
4242 ********************************************************************/
4243
4244 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4245                                            const struct auth_serversupplied_info *session_info,
4246                                            struct messaging_context *msg_ctx,
4247                                            const char *servername,
4248                                            uint32_t level,
4249                                            uint32_t flags,
4250                                            union spoolss_PrinterInfo **info_p,
4251                                            uint32_t *count_p)
4252 {
4253         int snum;
4254         int n_services = lp_numservices();
4255         union spoolss_PrinterInfo *info = NULL;
4256         uint32_t count = 0;
4257         WERROR result = WERR_OK;
4258         struct dcerpc_binding_handle *b = NULL;
4259
4260         *count_p = 0;
4261         *info_p = NULL;
4262
4263         for (snum = 0; snum < n_services; snum++) {
4264
4265                 const char *printer;
4266                 struct spoolss_PrinterInfo2 *info2;
4267
4268                 if (!snum_is_shared_printer(snum)) {
4269                         continue;
4270                 }
4271
4272                 printer = lp_const_servicename(snum);
4273
4274                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4275                         printer, snum));
4276
4277                 if (b == NULL) {
4278                         result = winreg_printer_binding_handle(mem_ctx,
4279                                                                session_info,
4280                                                                msg_ctx,
4281                                                                &b);
4282                         if (!W_ERROR_IS_OK(result)) {
4283                                 goto out;
4284                         }
4285                 }
4286
4287                 result = winreg_create_printer(mem_ctx, b,
4288                                                printer);
4289                 if (!W_ERROR_IS_OK(result)) {
4290                         goto out;
4291                 }
4292
4293                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4294                                             union spoolss_PrinterInfo,
4295                                             count + 1);
4296                 if (!info) {
4297                         result = WERR_NOMEM;
4298                         goto out;
4299                 }
4300
4301                 result = winreg_get_printer(mem_ctx, b,
4302                                             printer, &info2);
4303                 if (!W_ERROR_IS_OK(result)) {
4304                         goto out;
4305                 }
4306
4307                 switch (level) {
4308                 case 0:
4309                         result = construct_printer_info0(info, session_info,
4310                                                          msg_ctx, info2,
4311                                                          servername,
4312                                                          &info[count].info0, snum);
4313                         break;
4314                 case 1:
4315                         result = construct_printer_info1(info, info2, flags,
4316                                                          servername,
4317                                                          &info[count].info1, snum);
4318                         break;
4319                 case 2:
4320                         result = construct_printer_info2(info, msg_ctx, info2,
4321                                                          servername,
4322                                                          &info[count].info2, snum);
4323                         break;
4324                 case 4:
4325                         result = construct_printer_info4(info, info2,
4326                                                          servername,
4327                                                          &info[count].info4, snum);
4328                         break;
4329                 case 5:
4330                         result = construct_printer_info5(info, info2,
4331                                                          servername,
4332                                                          &info[count].info5, snum);
4333                         break;
4334
4335                 default:
4336                         result = WERR_UNKNOWN_LEVEL;
4337                         goto out;
4338                 }
4339
4340                 if (!W_ERROR_IS_OK(result)) {
4341                         goto out;
4342                 }
4343
4344                 count++;
4345         }
4346
4347         *count_p = count;
4348         *info_p = info;
4349
4350  out:
4351         if (!W_ERROR_IS_OK(result)) {
4352                 TALLOC_FREE(info);
4353                 return result;
4354         }
4355
4356         *info_p = info;
4357
4358         return WERR_OK;
4359 }
4360
4361 /********************************************************************
4362  * handle enumeration of printers at level 0
4363  ********************************************************************/
4364
4365 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4366                                   const struct auth_serversupplied_info *session_info,
4367                                   struct messaging_context *msg_ctx,
4368                                   uint32_t flags,
4369                                   const char *servername,
4370                                   union spoolss_PrinterInfo **info,
4371                                   uint32_t *count)
4372 {
4373         DEBUG(4,("enum_all_printers_info_0\n"));
4374
4375         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4376                                             servername, 0, flags, info, count);
4377 }
4378
4379
4380 /********************************************************************
4381 ********************************************************************/
4382
4383 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4384                                        const struct auth_serversupplied_info *session_info,
4385                                        struct messaging_context *msg_ctx,
4386                                        const char *servername,
4387                                        uint32_t flags,
4388                                        union spoolss_PrinterInfo **info,
4389                                        uint32_t *count)
4390 {
4391         DEBUG(4,("enum_all_printers_info_1\n"));
4392
4393         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4394                                             servername, 1, flags, info, count);
4395 }
4396
4397 /********************************************************************
4398  enum_all_printers_info_1_local.
4399 *********************************************************************/
4400
4401 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4402                                              const struct auth_serversupplied_info *session_info,
4403                                              struct messaging_context *msg_ctx,
4404                                              const char *servername,
4405                                              union spoolss_PrinterInfo **info,
4406                                              uint32_t *count)
4407 {
4408         DEBUG(4,("enum_all_printers_info_1_local\n"));
4409
4410         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4411                                         servername, PRINTER_ENUM_ICON8, info, count);
4412 }
4413
4414 /********************************************************************
4415  enum_all_printers_info_1_name.
4416 *********************************************************************/
4417
4418 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4419                                             const struct auth_serversupplied_info *session_info,
4420                                             struct messaging_context *msg_ctx,
4421                                             const char *servername,
4422                                             union spoolss_PrinterInfo **info,
4423                                             uint32_t *count)
4424 {
4425         const char *s = servername;
4426
4427         DEBUG(4,("enum_all_printers_info_1_name\n"));
4428
4429         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4430                 s = servername + 2;
4431         }
4432
4433         if (!is_myname_or_ipaddr(s)) {
4434                 return WERR_INVALID_NAME;
4435         }
4436
4437         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4438                                         servername, PRINTER_ENUM_ICON8, info, count);
4439 }
4440
4441 /********************************************************************
4442  enum_all_printers_info_1_network.
4443 *********************************************************************/
4444
4445 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4446                                                const struct auth_serversupplied_info *session_info,
4447                                                struct messaging_context *msg_ctx,
4448                                                const char *servername,
4449                                                union spoolss_PrinterInfo **info,
4450                                                uint32_t *count)
4451 {
4452         const char *s = servername;
4453
4454         DEBUG(4,("enum_all_printers_info_1_network\n"));
4455
4456         /* If we respond to a enum_printers level 1 on our name with flags
4457            set to PRINTER_ENUM_REMOTE with a list of printers then these
4458            printers incorrectly appear in the APW browse list.
4459            Specifically the printers for the server appear at the workgroup
4460            level where all the other servers in the domain are
4461            listed. Windows responds to this call with a
4462            WERR_CAN_NOT_COMPLETE so we should do the same. */
4463
4464         if (servername[0] == '\\' && servername[1] == '\\') {
4465                  s = servername + 2;
4466         }
4467
4468         if (is_myname_or_ipaddr(s)) {
4469                  return WERR_CAN_NOT_COMPLETE;
4470         }
4471
4472         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4473                                         servername, PRINTER_ENUM_NAME, info, count);
4474 }
4475
4476 /********************************************************************
4477  * api_spoolss_enumprinters
4478  *
4479  * called from api_spoolss_enumprinters (see this to understand)
4480  ********************************************************************/
4481
4482 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4483                                        const struct auth_serversupplied_info *session_info,
4484                                        struct messaging_context *msg_ctx,
4485                                        const char *servername,
4486                                        union spoolss_PrinterInfo **info,
4487                                        uint32_t *count)
4488 {
4489         DEBUG(4,("enum_all_printers_info_2\n"));
4490
4491         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4492                                             servername, 2, 0, info, count);
4493 }
4494
4495 /********************************************************************
4496  * handle enumeration of printers at level 1
4497  ********************************************************************/
4498
4499 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4500                                   const struct auth_serversupplied_info *session_info,
4501                                   struct messaging_context *msg_ctx,
4502                                   uint32_t flags,
4503                                   const char *servername,
4504                                   union spoolss_PrinterInfo **info,
4505                                   uint32_t *count)
4506 {
4507         /* Not all the flags are equals */
4508
4509         if (flags & PRINTER_ENUM_LOCAL) {
4510                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4511                                                       msg_ctx, servername, info, count);
4512         }
4513
4514         if (flags & PRINTER_ENUM_NAME) {
4515                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4516                                                      msg_ctx, servername, info,
4517                                                      count);
4518         }
4519
4520         if (flags & PRINTER_ENUM_NETWORK) {
4521                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4522                                                         msg_ctx, servername, info,
4523                                                         count);
4524         }
4525
4526         return WERR_OK; /* NT4sp5 does that */
4527 }
4528
4529 /********************************************************************
4530  * handle enumeration of printers at level 2
4531  ********************************************************************/
4532
4533 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4534                                   const struct auth_serversupplied_info *session_info,
4535                                   struct messaging_context *msg_ctx,
4536                                   uint32_t flags,
4537                                   const char *servername,
4538                                   union spoolss_PrinterInfo **info,
4539                                   uint32_t *count)
4540 {
4541         if (flags & PRINTER_ENUM_LOCAL) {
4542
4543                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4544                                                 servername,
4545                                                 info, count);
4546         }
4547
4548         if (flags & PRINTER_ENUM_NAME) {
4549                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4550                         return WERR_INVALID_NAME;
4551                 }
4552
4553                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4554                                                 servername,
4555                                                 info, count);
4556         }
4557
4558         if (flags & PRINTER_ENUM_REMOTE) {
4559                 return WERR_UNKNOWN_LEVEL;
4560         }
4561
4562         return WERR_OK;
4563 }
4564
4565 /********************************************************************
4566  * handle enumeration of printers at level 4
4567  ********************************************************************/
4568
4569 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4570                                   const struct auth_serversupplied_info *session_info,
4571                                   struct messaging_context *msg_ctx,
4572                                   uint32_t flags,
4573                                   const char *servername,
4574                                   union spoolss_PrinterInfo **info,
4575                                   uint32_t *count)
4576 {
4577         DEBUG(4,("enum_all_printers_info_4\n"));
4578
4579         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4580                                             servername, 4, flags, info, count);
4581 }
4582
4583
4584 /********************************************************************
4585  * handle enumeration of printers at level 5
4586  ********************************************************************/
4587
4588 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4589                                   const struct auth_serversupplied_info *session_info,
4590                                   struct messaging_context *msg_ctx,
4591                                   uint32_t flags,
4592                                   const char *servername,
4593                                   union spoolss_PrinterInfo **info,
4594                                   uint32_t *count)
4595 {
4596         DEBUG(4,("enum_all_printers_info_5\n"));
4597
4598         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4599                                             servername, 5, flags, info, count);
4600 }
4601
4602 /****************************************************************
4603  _spoolss_EnumPrinters
4604 ****************************************************************/
4605
4606 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4607                              struct spoolss_EnumPrinters *r)
4608 {
4609         const struct auth_serversupplied_info *session_info = get_session_info_system();
4610         WERROR result;
4611
4612         /* that's an [in out] buffer */
4613
4614         if (!r->in.buffer && (r->in.offered != 0)) {
4615                 return WERR_INVALID_PARAM;
4616         }
4617
4618         DEBUG(4,("_spoolss_EnumPrinters\n"));
4619
4620         *r->out.needed = 0;
4621         *r->out.count = 0;
4622         *r->out.info = NULL;
4623
4624         /*
4625          * Level 1:
4626          *          flags==PRINTER_ENUM_NAME
4627          *           if name=="" then enumerates all printers
4628          *           if name!="" then enumerate the printer
4629          *          flags==PRINTER_ENUM_REMOTE
4630          *          name is NULL, enumerate printers
4631          * Level 2: name!="" enumerates printers, name can't be NULL
4632          * Level 3: doesn't exist
4633          * Level 4: does a local registry lookup
4634          * Level 5: same as Level 2
4635          */
4636
4637         if (r->in.server && r->in.server[0] == '\0') {
4638                 r->in.server = NULL;
4639         }
4640
4641         switch (r->in.level) {
4642         case 0:
4643                 result = enumprinters_level0(p->mem_ctx, session_info,
4644                                              p->msg_ctx, r->in.flags,
4645                                              r->in.server,
4646                                              r->out.info, r->out.count);
4647                 break;
4648         case 1:
4649                 result = enumprinters_level1(p->mem_ctx, session_info,
4650                                              p->msg_ctx, r->in.flags,
4651                                              r->in.server,
4652                                              r->out.info, r->out.count);
4653                 break;
4654         case 2:
4655                 result = enumprinters_level2(p->mem_ctx, session_info,
4656                                              p->msg_ctx, r->in.flags,
4657                                              r->in.server,
4658                                              r->out.info, r->out.count);
4659                 break;
4660         case 4:
4661                 result = enumprinters_level4(p->mem_ctx, session_info,
4662                                              p->msg_ctx, r->in.flags,
4663                                              r->in.server,
4664                                              r->out.info, r->out.count);
4665                 break;
4666         case 5:
4667                 result = enumprinters_level5(p->mem_ctx, session_info,
4668                                              p->msg_ctx, r->in.flags,
4669                                              r->in.server,
4670                                              r->out.info, r->out.count);
4671                 break;
4672         default:
4673                 return WERR_UNKNOWN_LEVEL;
4674         }
4675
4676         if (!W_ERROR_IS_OK(result)) {
4677                 return result;
4678         }
4679
4680         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4681                                                      spoolss_EnumPrinters,
4682                                                      *r->out.info, r->in.level,
4683                                                      *r->out.count);
4684         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4685         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4686
4687         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4688 }
4689
4690 /****************************************************************
4691  _spoolss_GetPrinter
4692 ****************************************************************/
4693
4694 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4695                            struct spoolss_GetPrinter *r)
4696 {
4697         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4698         struct spoolss_PrinterInfo2 *info2 = NULL;
4699         WERROR result = WERR_OK;
4700         int snum;
4701
4702         /* that's an [in out] buffer */
4703
4704         if (!r->in.buffer && (r->in.offered != 0)) {
4705                 return WERR_INVALID_PARAM;
4706         }
4707
4708         *r->out.needed = 0;
4709
4710         if (Printer == NULL) {
4711                 return WERR_BADFID;
4712         }
4713
4714         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4715                 return WERR_BADFID;
4716         }
4717
4718         result = winreg_get_printer_internal(p->mem_ctx,
4719                                     get_session_info_system(),
4720                                     p->msg_ctx,
4721                                     lp_const_servicename(snum),
4722                                     &info2);
4723         if (!W_ERROR_IS_OK(result)) {
4724                 goto out;
4725         }
4726
4727         switch (r->in.level) {
4728         case 0:
4729                 result = construct_printer_info0(p->mem_ctx,
4730                                                  get_session_info_system(),
4731                                                  p->msg_ctx,
4732                                                  info2,
4733                                                  Printer->servername,
4734                                                  &r->out.info->info0,
4735                                                  snum);
4736                 break;
4737         case 1:
4738                 result = construct_printer_info1(p->mem_ctx, info2,
4739                                                  PRINTER_ENUM_ICON8,
4740                                                  Printer->servername,
4741                                                  &r->out.info->info1, snum);
4742                 break;
4743         case 2:
4744                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4745                                                  Printer->servername,
4746                                                  &r->out.info->info2, snum);
4747                 break;
4748         case 3:
4749                 result = construct_printer_info3(p->mem_ctx, info2,
4750                                                  Printer->servername,
4751                                                  &r->out.info->info3, snum);
4752                 break;
4753         case 4:
4754                 result = construct_printer_info4(p->mem_ctx, info2,
4755                                                  Printer->servername,
4756                                                  &r->out.info->info4, snum);
4757                 break;
4758         case 5:
4759                 result = construct_printer_info5(p->mem_ctx, info2,
4760                                                  Printer->servername,
4761                                                  &r->out.info->info5, snum);
4762                 break;
4763         case 6:
4764                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4765                                                  Printer->servername,
4766                                                  &r->out.info->info6, snum);
4767                 break;
4768         case 7:
4769                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4770                                                  Printer->servername,
4771                                                  &r->out.info->info7, snum);
4772                 break;
4773         case 8:
4774                 result = construct_printer_info8(p->mem_ctx, info2,
4775                                                  Printer->servername,
4776                                                  &r->out.info->info8, snum);
4777                 break;
4778         default:
4779                 result = WERR_UNKNOWN_LEVEL;
4780                 break;
4781         }
4782
4783  out:
4784         if (!W_ERROR_IS_OK(result)) {
4785                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4786                           r->in.level, win_errstr(result)));
4787                 TALLOC_FREE(r->out.info);
4788                 return result;
4789         }
4790
4791         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4792                                                r->out.info, r->in.level);
4793         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4794
4795         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4796 }
4797
4798 /********************************************************************
4799  ********************************************************************/
4800
4801 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4802         do { \
4803                 if (in && strlen(in)) { \
4804                         out = talloc_strdup(mem_ctx, in); \
4805                 } else { \
4806                         out = talloc_strdup(mem_ctx, ""); \
4807                 } \
4808                 W_ERROR_HAVE_NO_MEMORY(out); \
4809         } while (0);
4810
4811 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4812         do { \
4813                 if (in && strlen(in)) { \
4814                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4815                 } else { \
4816                         out = talloc_strdup(mem_ctx, ""); \
4817                 } \
4818                 W_ERROR_HAVE_NO_MEMORY(out); \
4819         } while (0);
4820
4821 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4822                                                   const char **string_array,
4823                                                   const char ***presult,
4824                                                   const char *cservername,
4825                                                   const char *arch,
4826                                                   int version)
4827 {
4828         int i, num_strings = 0;
4829         const char **array = NULL;
4830
4831         if (string_array == NULL) {
4832                 return WERR_INVALID_PARAMETER;
4833         }
4834
4835         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4836                 const char *str = NULL;
4837
4838                 if (cservername == NULL || arch == NULL) {
4839                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4840                 } else {
4841                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4842                 }
4843
4844                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4845                         TALLOC_FREE(array);
4846                         return WERR_NOMEM;
4847                 }
4848         }
4849
4850         if (i > 0) {
4851                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4852                              &array, &num_strings);
4853         }
4854
4855         if (presult) {
4856                 *presult = array;
4857         }
4858
4859         return WERR_OK;
4860 }
4861
4862 /********************************************************************
4863  * fill a spoolss_DriverInfo1 struct
4864  ********************************************************************/
4865
4866 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4867                                         struct spoolss_DriverInfo1 *r,
4868                                         const struct spoolss_DriverInfo8 *driver,
4869                                         const char *servername)
4870 {
4871         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4872         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4873
4874         return WERR_OK;
4875 }
4876
4877 /********************************************************************
4878  * fill a spoolss_DriverInfo2 struct
4879  ********************************************************************/
4880
4881 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4882                                         struct spoolss_DriverInfo2 *r,
4883                                         const struct spoolss_DriverInfo8 *driver,
4884                                         const char *servername)
4885
4886 {
4887         const char *cservername = canon_servername(servername);
4888
4889         r->version              = driver->version;
4890
4891         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4892         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4893         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4894         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4895
4896         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4897                                driver->architecture,
4898                                driver->version,
4899                                driver->driver_path,
4900                                r->driver_path);
4901
4902         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4903                                driver->architecture,
4904                                driver->version,
4905                                driver->data_file,
4906                                r->data_file);
4907
4908         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4909                                driver->architecture,
4910                                driver->version,
4911                                driver->config_file,
4912                                r->config_file);
4913
4914         return WERR_OK;
4915 }
4916
4917 /********************************************************************
4918  * fill a spoolss_DriverInfo3 struct
4919  ********************************************************************/
4920
4921 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4922                                         struct spoolss_DriverInfo3 *r,
4923                                         const struct spoolss_DriverInfo8 *driver,
4924                                         const char *servername)
4925 {
4926         const char *cservername = canon_servername(servername);
4927
4928         r->version              = driver->version;
4929
4930         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4931         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4932         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4933         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4934
4935         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4936                                driver->architecture,
4937                                driver->version,
4938                                driver->driver_path,
4939                                r->driver_path);
4940
4941         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4942                                driver->architecture,
4943                                driver->version,
4944                                driver->data_file,
4945                                r->data_file);
4946
4947         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4948                                driver->architecture,
4949                                driver->version,
4950                                driver->config_file,
4951                                r->config_file);
4952
4953         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954                                driver->architecture,
4955                                driver->version,
4956                                driver->help_file,
4957                                r->help_file);
4958
4959         FILL_DRIVER_STRING(mem_ctx,
4960                            driver->monitor_name,
4961                            r->monitor_name);
4962
4963         FILL_DRIVER_STRING(mem_ctx,
4964                            driver->default_datatype,
4965                            r->default_datatype);
4966
4967         return string_array_from_driver_info(mem_ctx,
4968                                              driver->dependent_files,
4969                                              &r->dependent_files,
4970                                              cservername,
4971                                              driver->architecture,
4972                                              driver->version);
4973 }
4974
4975 /********************************************************************
4976  * fill a spoolss_DriverInfo4 struct
4977  ********************************************************************/
4978
4979 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4980                                         struct spoolss_DriverInfo4 *r,
4981                                         const struct spoolss_DriverInfo8 *driver,
4982                                         const char *servername)
4983 {
4984         const char *cservername = canon_servername(servername);
4985         WERROR result;
4986
4987         r->version              = driver->version;
4988
4989         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4990         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4991         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4992         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4993
4994         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995                                driver->architecture,
4996                                driver->version,
4997                                driver->driver_path,
4998                                r->driver_path);
4999
5000         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001                                driver->architecture,
5002                                driver->version,
5003                                driver->data_file,
5004                                r->data_file);
5005
5006         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007                                driver->architecture,
5008                                driver->version,
5009                                driver->config_file,
5010                                r->config_file);
5011
5012         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013                                driver->architecture,
5014                                driver->version,
5015                                driver->help_file,
5016                                r->help_file);
5017
5018         result = string_array_from_driver_info(mem_ctx,
5019                                                driver->dependent_files,
5020                                                &r->dependent_files,
5021                                                cservername,
5022                                                driver->architecture,
5023                                                driver->version);
5024         if (!W_ERROR_IS_OK(result)) {
5025                 return result;
5026         }
5027
5028         FILL_DRIVER_STRING(mem_ctx,
5029                            driver->monitor_name,
5030                            r->monitor_name);
5031
5032         FILL_DRIVER_STRING(mem_ctx,
5033                            driver->default_datatype,
5034                            r->default_datatype);
5035
5036
5037         result = string_array_from_driver_info(mem_ctx,
5038                                                driver->previous_names,
5039                                                &r->previous_names,
5040                                                NULL, NULL, 0);
5041
5042         return result;
5043 }
5044
5045 /********************************************************************
5046  * fill a spoolss_DriverInfo5 struct
5047  ********************************************************************/
5048
5049 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5050                                         struct spoolss_DriverInfo5 *r,
5051                                         const struct spoolss_DriverInfo8 *driver,
5052                                         const char *servername)
5053 {
5054         const char *cservername = canon_servername(servername);
5055
5056         r->version              = driver->version;
5057
5058         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5059         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5060         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5061         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5062
5063         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5064                                driver->architecture,
5065                                driver->version,
5066                                driver->driver_path,
5067                                r->driver_path);
5068
5069         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070                                driver->architecture,
5071                                driver->version,
5072                                driver->data_file,
5073                                r->data_file);
5074
5075         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076                                driver->architecture,
5077                                driver->version,
5078                                driver->config_file,
5079                                r->config_file);
5080
5081         r->driver_attributes    = 0;
5082         r->config_version       = 0;
5083         r->driver_version       = 0;
5084
5085         return WERR_OK;
5086 }
5087 /********************************************************************
5088  * fill a spoolss_DriverInfo6 struct
5089  ********************************************************************/
5090
5091 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5092                                         struct spoolss_DriverInfo6 *r,
5093                                         const struct spoolss_DriverInfo8 *driver,
5094                                         const char *servername)
5095 {
5096         const char *cservername = canon_servername(servername);
5097         WERROR result;
5098
5099         r->version              = driver->version;
5100
5101         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5102         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5103         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5104         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5105
5106         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107                                driver->architecture,
5108                                driver->version,
5109                                driver->driver_path,
5110                                r->driver_path);
5111
5112         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113                                driver->architecture,
5114                                driver->version,
5115                                driver->data_file,
5116                                r->data_file);
5117
5118         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119                                driver->architecture,
5120                                driver->version,
5121                                driver->config_file,
5122                                r->config_file);
5123
5124         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125                                driver->architecture,
5126                                driver->version,
5127                                driver->help_file,
5128                                r->help_file);
5129
5130         FILL_DRIVER_STRING(mem_ctx,
5131                            driver->monitor_name,
5132                            r->monitor_name);
5133
5134         FILL_DRIVER_STRING(mem_ctx,
5135                            driver->default_datatype,
5136                            r->default_datatype);
5137
5138         result = string_array_from_driver_info(mem_ctx,
5139                                                driver->dependent_files,
5140                                                &r->dependent_files,
5141                                                cservername,
5142                                                driver->architecture,
5143                                                driver->version);
5144         if (!W_ERROR_IS_OK(result)) {
5145                 return result;
5146         }
5147
5148         result = string_array_from_driver_info(mem_ctx,
5149                                                driver->previous_names,
5150                                                &r->previous_names,
5151                                                NULL, NULL, 0);
5152         if (!W_ERROR_IS_OK(result)) {
5153                 return result;
5154         }
5155
5156         r->driver_date          = driver->driver_date;
5157         r->driver_version       = driver->driver_version;
5158
5159         FILL_DRIVER_STRING(mem_ctx,
5160                            driver->manufacturer_name,
5161                            r->manufacturer_name);
5162         FILL_DRIVER_STRING(mem_ctx,
5163                            driver->manufacturer_url,
5164                            r->manufacturer_url);
5165         FILL_DRIVER_STRING(mem_ctx,
5166                            driver->hardware_id,
5167                            r->hardware_id);
5168         FILL_DRIVER_STRING(mem_ctx,
5169                            driver->provider,
5170                            r->provider);
5171
5172         return WERR_OK;
5173 }
5174
5175 /********************************************************************
5176  * fill a spoolss_DriverInfo8 struct
5177  ********************************************************************/
5178
5179 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5180                                         struct spoolss_DriverInfo8 *r,
5181                                         const struct spoolss_DriverInfo8 *driver,
5182                                         const char *servername)
5183 {
5184         const char *cservername = canon_servername(servername);
5185         WERROR result;
5186
5187         r->version              = driver->version;
5188
5189         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5190         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5191         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5192         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5193
5194         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5195                                driver->architecture,
5196                                driver->version,
5197                                driver->driver_path,
5198                                r->driver_path);
5199
5200         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5201                                driver->architecture,
5202                                driver->version,
5203                                driver->data_file,
5204                                r->data_file);
5205
5206         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5207                                driver->architecture,
5208                                driver->version,
5209                                driver->config_file,
5210                                r->config_file);
5211
5212         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213                                driver->architecture,
5214                                driver->version,
5215                                driver->help_file,
5216                                r->help_file);
5217
5218         FILL_DRIVER_STRING(mem_ctx,
5219                            driver->monitor_name,
5220                            r->monitor_name);
5221
5222         FILL_DRIVER_STRING(mem_ctx,
5223                            driver->default_datatype,
5224                            r->default_datatype);
5225
5226         result = string_array_from_driver_info(mem_ctx,
5227                                                driver->dependent_files,
5228                                                &r->dependent_files,
5229                                                cservername,
5230                                                driver->architecture,
5231                                                driver->version);
5232         if (!W_ERROR_IS_OK(result)) {
5233                 return result;
5234         }
5235
5236         result = string_array_from_driver_info(mem_ctx,
5237                                                driver->previous_names,
5238                                                &r->previous_names,
5239                                                NULL, NULL, 0);
5240         if (!W_ERROR_IS_OK(result)) {
5241                 return result;
5242         }
5243
5244         r->driver_date          = driver->driver_date;
5245         r->driver_version       = driver->driver_version;
5246
5247         FILL_DRIVER_STRING(mem_ctx,
5248                            driver->manufacturer_name,
5249                            r->manufacturer_name);
5250         FILL_DRIVER_STRING(mem_ctx,
5251                            driver->manufacturer_url,
5252                            r->manufacturer_url);
5253         FILL_DRIVER_STRING(mem_ctx,
5254                            driver->hardware_id,
5255                            r->hardware_id);
5256         FILL_DRIVER_STRING(mem_ctx,
5257                            driver->provider,
5258                            r->provider);
5259
5260         FILL_DRIVER_STRING(mem_ctx,
5261                            driver->print_processor,
5262                            r->print_processor);
5263         FILL_DRIVER_STRING(mem_ctx,
5264                            driver->vendor_setup,
5265                            r->vendor_setup);
5266
5267         result = string_array_from_driver_info(mem_ctx,
5268                                                driver->color_profiles,
5269                                                &r->color_profiles,
5270                                                NULL, NULL, 0);
5271         if (!W_ERROR_IS_OK(result)) {
5272                 return result;
5273         }
5274
5275         FILL_DRIVER_STRING(mem_ctx,
5276                            driver->inf_path,
5277                            r->inf_path);
5278
5279         r->printer_driver_attributes    = driver->printer_driver_attributes;
5280
5281         result = string_array_from_driver_info(mem_ctx,
5282                                                driver->core_driver_dependencies,
5283                                                &r->core_driver_dependencies,
5284                                                NULL, NULL, 0);
5285         if (!W_ERROR_IS_OK(result)) {
5286                 return result;
5287         }
5288
5289         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5290         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5291
5292         return WERR_OK;
5293 }
5294
5295 #if 0 /* disabled until marshalling issues are resolved - gd */
5296 /********************************************************************
5297  ********************************************************************/
5298
5299 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5300                                           struct spoolss_DriverFileInfo *r,
5301                                           const char *cservername,
5302                                           const char *file_name,
5303                                           enum spoolss_DriverFileType file_type,
5304                                           uint32_t file_version)
5305 {
5306         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5307                                           cservername, file_name);
5308         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5309         r->file_type    = file_type;
5310         r->file_version = file_version;
5311
5312         return WERR_OK;
5313 }
5314
5315 /********************************************************************
5316  ********************************************************************/
5317
5318 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5319                                                  const struct spoolss_DriverInfo8 *driver,
5320                                                  const char *cservername,
5321                                                  struct spoolss_DriverFileInfo **info_p,
5322                                                  uint32_t *count_p)
5323 {
5324         struct spoolss_DriverFileInfo *info = NULL;
5325         uint32_t count = 0;
5326         WERROR result;
5327         uint32_t i;
5328
5329         *info_p = NULL;
5330         *count_p = 0;
5331
5332         if (strlen(driver->driver_path)) {
5333                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5334                                             struct spoolss_DriverFileInfo,
5335                                             count + 1);
5336                 W_ERROR_HAVE_NO_MEMORY(info);
5337                 result = fill_spoolss_DriverFileInfo(info,
5338                                                      &info[count],
5339                                                      cservername,
5340                                                      driver->driver_path,
5341                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5342                                                      0);
5343                 W_ERROR_NOT_OK_RETURN(result);
5344                 count++;
5345         }
5346
5347         if (strlen(driver->config_file)) {
5348                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5349                                             struct spoolss_DriverFileInfo,
5350                                             count + 1);
5351                 W_ERROR_HAVE_NO_MEMORY(info);
5352                 result = fill_spoolss_DriverFileInfo(info,
5353                                                      &info[count],
5354                                                      cservername,
5355                                                      driver->config_file,
5356                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5357                                                      0);
5358                 W_ERROR_NOT_OK_RETURN(result);
5359                 count++;
5360         }
5361
5362         if (strlen(driver->data_file)) {
5363                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5364                                             struct spoolss_DriverFileInfo,
5365                                             count + 1);
5366                 W_ERROR_HAVE_NO_MEMORY(info);
5367                 result = fill_spoolss_DriverFileInfo(info,
5368                                                      &info[count],
5369                                                      cservername,
5370                                                      driver->data_file,
5371                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5372                                                      0);
5373                 W_ERROR_NOT_OK_RETURN(result);
5374                 count++;
5375         }
5376
5377         if (strlen(driver->help_file)) {
5378                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5379                                             struct spoolss_DriverFileInfo,
5380                                             count + 1);
5381                 W_ERROR_HAVE_NO_MEMORY(info);
5382                 result = fill_spoolss_DriverFileInfo(info,
5383                                                      &info[count],
5384                                                      cservername,
5385                                                      driver->help_file,
5386                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5387                                                      0);
5388                 W_ERROR_NOT_OK_RETURN(result);
5389                 count++;
5390         }
5391
5392         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5393                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5394                                             struct spoolss_DriverFileInfo,
5395                                             count + 1);
5396                 W_ERROR_HAVE_NO_MEMORY(info);
5397                 result = fill_spoolss_DriverFileInfo(info,
5398                                                      &info[count],
5399                                                      cservername,
5400                                                      driver->dependent_files[i],
5401                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5402                                                      0);
5403                 W_ERROR_NOT_OK_RETURN(result);
5404                 count++;
5405         }
5406
5407         *info_p = info;
5408         *count_p = count;
5409
5410         return WERR_OK;
5411 }
5412
5413 /********************************************************************
5414  * fill a spoolss_DriverInfo101 struct
5415  ********************************************************************/
5416
5417 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5418                                           struct spoolss_DriverInfo101 *r,
5419                                           const struct spoolss_DriverInfo8 *driver,
5420                                           const char *servername)
5421 {
5422         const char *cservername = canon_servername(servername);
5423         WERROR result;
5424
5425         r->version              = driver->version;
5426
5427         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5428         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5429         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5430         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5431
5432         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5433                                                     cservername,
5434                                                     &r->file_info,
5435                                                     &r->file_count);
5436         if (!W_ERROR_IS_OK(result)) {
5437                 return result;
5438         }
5439
5440         FILL_DRIVER_STRING(mem_ctx,
5441                            driver->monitor_name,
5442                            r->monitor_name);
5443
5444         FILL_DRIVER_STRING(mem_ctx,
5445                            driver->default_datatype,
5446                            r->default_datatype);
5447
5448         result = string_array_from_driver_info(mem_ctx,
5449                                                driver->previous_names,
5450                                                &r->previous_names,
5451                                                NULL, NULL, 0);
5452         if (!W_ERROR_IS_OK(result)) {
5453                 return result;
5454         }
5455
5456         r->driver_date          = driver->driver_date;
5457         r->driver_version       = driver->driver_version;
5458
5459         FILL_DRIVER_STRING(mem_ctx,
5460                            driver->manufacturer_name,
5461                            r->manufacturer_name);
5462         FILL_DRIVER_STRING(mem_ctx,
5463                            driver->manufacturer_url,
5464                            r->manufacturer_url);
5465         FILL_DRIVER_STRING(mem_ctx,
5466                            driver->hardware_id,
5467                            r->hardware_id);
5468         FILL_DRIVER_STRING(mem_ctx,
5469                            driver->provider,
5470                            r->provider);
5471
5472         return WERR_OK;
5473 }
5474 #endif
5475 /********************************************************************
5476  ********************************************************************/
5477
5478 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5479                                                   const struct auth_serversupplied_info *session_info,
5480                                                   struct messaging_context *msg_ctx,
5481                                                   uint32_t level,
5482                                                   union spoolss_DriverInfo *r,
5483                                                   int snum,
5484                                                   const char *servername,
5485                                                   const char *architecture,
5486                                                   uint32_t version)
5487 {
5488         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5489         struct spoolss_DriverInfo8 *driver;
5490         WERROR result;
5491         struct dcerpc_binding_handle *b;
5492
5493         if (level == 101) {
5494                 return WERR_UNKNOWN_LEVEL;
5495         }
5496
5497         result = winreg_printer_binding_handle(mem_ctx,
5498                                                session_info,
5499                                                msg_ctx,
5500                                                &b);
5501         if (!W_ERROR_IS_OK(result)) {
5502                 return result;
5503         }
5504
5505         result = winreg_get_printer(mem_ctx, b,
5506                                     lp_const_servicename(snum),
5507                                     &pinfo2);
5508
5509         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5510                 win_errstr(result)));
5511
5512         if (!W_ERROR_IS_OK(result)) {
5513                 return WERR_INVALID_PRINTER_NAME;
5514         }
5515
5516         result = winreg_get_driver(mem_ctx, b,
5517                                    architecture,
5518                                    pinfo2->drivername, version, &driver);
5519
5520         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5521                 win_errstr(result)));
5522
5523         if (!W_ERROR_IS_OK(result)) {
5524                 /*
5525                  * Is this a W2k client ?
5526                  */
5527
5528                 if (version < 3) {
5529                         talloc_free(pinfo2);
5530                         return WERR_UNKNOWN_PRINTER_DRIVER;
5531                 }
5532
5533                 /* Yes - try again with a WinNT driver. */
5534                 version = 2;
5535                 result = winreg_get_driver(mem_ctx, b,
5536                                            architecture,
5537                                            pinfo2->drivername,
5538                                            version, &driver);
5539                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5540                         win_errstr(result)));
5541                 if (!W_ERROR_IS_OK(result)) {
5542                         talloc_free(pinfo2);
5543                         return WERR_UNKNOWN_PRINTER_DRIVER;
5544                 }
5545         }
5546
5547         switch (level) {
5548         case 1:
5549                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5550                 break;
5551         case 2:
5552                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5553                 break;
5554         case 3:
5555                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5556                 break;
5557         case 4:
5558                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5559                 break;
5560         case 5:
5561                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5562                 break;
5563         case 6:
5564                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5565                 break;
5566         case 8:
5567                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5568                 break;
5569 #if 0 /* disabled until marshalling issues are resolved - gd */
5570         case 101:
5571                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5572                 break;
5573 #endif
5574         default:
5575                 result = WERR_UNKNOWN_LEVEL;
5576                 break;
5577         }
5578
5579         talloc_free(pinfo2);
5580         talloc_free(driver);
5581
5582         return result;
5583 }
5584
5585 /****************************************************************
5586  _spoolss_GetPrinterDriver2
5587 ****************************************************************/
5588
5589 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5590                                   struct spoolss_GetPrinterDriver2 *r)
5591 {
5592         struct printer_handle *printer;
5593         WERROR result;
5594
5595         int snum;
5596
5597         /* that's an [in out] buffer */
5598
5599         if (!r->in.buffer && (r->in.offered != 0)) {
5600                 return WERR_INVALID_PARAM;
5601         }
5602
5603         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5604
5605         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5606                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5607                 return WERR_INVALID_PRINTER_NAME;
5608         }
5609
5610         *r->out.needed = 0;
5611         *r->out.server_major_version = 0;
5612         *r->out.server_minor_version = 0;
5613
5614         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5615                 return WERR_BADFID;
5616         }
5617
5618         result = construct_printer_driver_info_level(p->mem_ctx,
5619                                                      get_session_info_system(),
5620                                                      p->msg_ctx,
5621                                                      r->in.level, r->out.info,
5622                                                      snum, printer->servername,
5623                                                      r->in.architecture,
5624                                                      r->in.client_major_version);
5625         if (!W_ERROR_IS_OK(result)) {
5626                 TALLOC_FREE(r->out.info);
5627                 return result;
5628         }
5629
5630         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5631                                                r->out.info, r->in.level);
5632         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5633
5634         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5635 }
5636
5637
5638 /****************************************************************
5639  _spoolss_StartPagePrinter
5640 ****************************************************************/
5641
5642 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5643                                  struct spoolss_StartPagePrinter *r)
5644 {
5645         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5646
5647         if (!Printer) {
5648                 DEBUG(3,("_spoolss_StartPagePrinter: "
5649                         "Error in startpageprinter printer handle\n"));
5650                 return WERR_BADFID;
5651         }
5652
5653         Printer->page_started = true;
5654         return WERR_OK;
5655 }
5656
5657 /****************************************************************
5658  _spoolss_EndPagePrinter
5659 ****************************************************************/
5660
5661 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5662                                struct spoolss_EndPagePrinter *r)
5663 {
5664         int snum;
5665
5666         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5667
5668         if (!Printer) {
5669                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5670                         OUR_HANDLE(r->in.handle)));
5671                 return WERR_BADFID;
5672         }
5673
5674         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5675                 return WERR_BADFID;
5676
5677         Printer->page_started = false;
5678         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5679
5680         return WERR_OK;
5681 }
5682
5683 /****************************************************************
5684  _spoolss_StartDocPrinter
5685 ****************************************************************/
5686
5687 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5688                                 struct spoolss_StartDocPrinter *r)
5689 {
5690         struct spoolss_DocumentInfo1 *info_1;
5691         int snum;
5692         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5693         WERROR werr;
5694
5695         if (!Printer) {
5696                 DEBUG(2,("_spoolss_StartDocPrinter: "
5697                         "Invalid handle (%s:%u:%u)\n",
5698                         OUR_HANDLE(r->in.handle)));
5699                 return WERR_BADFID;
5700         }
5701
5702         if (Printer->jobid) {
5703                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5704                           "StartDocPrinter called twice! "
5705                           "(existing jobid = %d)\n", Printer->jobid));
5706                 return WERR_INVALID_HANDLE;
5707         }
5708
5709         if (r->in.level != 1) {
5710                 return WERR_UNKNOWN_LEVEL;
5711         }
5712
5713         info_1 = r->in.info.info1;
5714
5715         /*
5716          * a nice thing with NT is it doesn't listen to what you tell it.
5717          * when asked to send _only_ RAW datas, it tries to send datas
5718          * in EMF format.
5719          *
5720          * So I add checks like in NT Server ...
5721          */
5722
5723         if (info_1->datatype) {
5724                 if (strcmp(info_1->datatype, "RAW") != 0) {
5725                         *r->out.job_id = 0;
5726                         return WERR_INVALID_DATATYPE;
5727                 }
5728         }
5729
5730         /* get the share number of the printer */
5731         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5732                 return WERR_BADFID;
5733         }
5734
5735         werr = print_job_start(p->session_info,
5736                                p->msg_ctx,
5737                                p->client_id->name,
5738                                snum,
5739                                info_1->document_name,
5740                                info_1->output_file,
5741                                Printer->devmode,
5742                                &Printer->jobid);
5743
5744         /* An error occured in print_job_start() so return an appropriate
5745            NT error code. */
5746
5747         if (!W_ERROR_IS_OK(werr)) {
5748                 return werr;
5749         }
5750
5751         Printer->document_started = true;
5752         *r->out.job_id = Printer->jobid;
5753
5754         return WERR_OK;
5755 }
5756
5757 /****************************************************************
5758  _spoolss_EndDocPrinter
5759 ****************************************************************/
5760
5761 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5762                               struct spoolss_EndDocPrinter *r)
5763 {
5764         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5765         NTSTATUS status;
5766         int snum;
5767
5768         if (!Printer) {
5769                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5770                         OUR_HANDLE(r->in.handle)));
5771                 return WERR_BADFID;
5772         }
5773
5774         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5775                 return WERR_BADFID;
5776         }
5777
5778         Printer->document_started = false;
5779         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5780         if (!NT_STATUS_IS_OK(status)) {
5781                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5782                           "print_job_end failed [%s]\n",
5783                           nt_errstr(status)));
5784         }
5785
5786         Printer->jobid = 0;
5787         return ntstatus_to_werror(status);
5788 }
5789
5790 /****************************************************************
5791  _spoolss_WritePrinter
5792 ****************************************************************/
5793
5794 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5795                              struct spoolss_WritePrinter *r)
5796 {
5797         ssize_t buffer_written;
5798         int snum;
5799         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5800
5801         if (!Printer) {
5802                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5803                         OUR_HANDLE(r->in.handle)));
5804                 *r->out.num_written = r->in._data_size;
5805                 return WERR_BADFID;
5806         }
5807
5808         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5809                 return WERR_BADFID;
5810
5811         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5812         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5813                                                    snum, Printer->jobid,
5814                                                    (const char *)r->in.data.data,
5815                                                    (size_t)r->in._data_size);
5816         if (buffer_written == (ssize_t)-1) {
5817                 *r->out.num_written = 0;
5818                 if (errno == ENOSPC)
5819                         return WERR_NO_SPOOL_SPACE;
5820                 else
5821                         return WERR_ACCESS_DENIED;
5822         }
5823
5824         *r->out.num_written = r->in._data_size;
5825
5826         return WERR_OK;
5827 }
5828
5829 /********************************************************************
5830  * api_spoolss_getprinter
5831  * called from the spoolss dispatcher
5832  *
5833  ********************************************************************/
5834
5835 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5836                               struct pipes_struct *p)
5837 {
5838         const struct auth_serversupplied_info *session_info = p->session_info;
5839         int snum;
5840         WERROR errcode = WERR_BADFUNC;
5841         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5842
5843         if (!Printer) {
5844                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5845                         OUR_HANDLE(handle)));
5846                 return WERR_BADFID;
5847         }
5848
5849         if (!get_printer_snum(p, handle, &snum, NULL))
5850                 return WERR_BADFID;
5851
5852         switch (command) {
5853         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5854                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5855                 break;
5856         case SPOOLSS_PRINTER_CONTROL_RESUME:
5857         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5858                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5859                 break;
5860         case SPOOLSS_PRINTER_CONTROL_PURGE:
5861                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5862                 break;
5863         default:
5864                 return WERR_UNKNOWN_LEVEL;
5865         }
5866
5867         return errcode;
5868 }
5869
5870
5871 /****************************************************************
5872  _spoolss_AbortPrinter
5873  * From MSDN: "Deletes printer's spool file if printer is configured
5874  * for spooling"
5875 ****************************************************************/
5876
5877 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5878                              struct spoolss_AbortPrinter *r)
5879 {
5880         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5881         int             snum;
5882         WERROR          errcode = WERR_OK;
5883
5884         if (!Printer) {
5885                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5886                         OUR_HANDLE(r->in.handle)));
5887                 return WERR_BADFID;
5888         }
5889
5890         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5891                 return WERR_BADFID;
5892
5893         if (!Printer->document_started) {
5894                 return WERR_SPL_NO_STARTDOC;
5895         }
5896
5897         errcode = print_job_delete(p->session_info,
5898                                    p->msg_ctx,
5899                                    snum,
5900                                    Printer->jobid);
5901
5902         return errcode;
5903 }
5904
5905 /********************************************************************
5906  * called by spoolss_api_setprinter
5907  * when updating a printer description
5908  ********************************************************************/
5909
5910 static WERROR update_printer_sec(struct policy_handle *handle,
5911                                  struct pipes_struct *p,
5912                                  struct sec_desc_buf *secdesc_ctr)
5913 {
5914         struct spoolss_security_descriptor *new_secdesc = NULL;
5915         struct spoolss_security_descriptor *old_secdesc = NULL;
5916         const char *printer;
5917         WERROR result;
5918         int snum;
5919         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5920         struct dcerpc_binding_handle *b;
5921
5922         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5923                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5924                          OUR_HANDLE(handle)));
5925
5926                 result = WERR_BADFID;
5927                 goto done;
5928         }
5929
5930         if (secdesc_ctr == NULL) {
5931                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5932                 result = WERR_INVALID_PARAM;
5933                 goto done;
5934         }
5935         printer = lp_const_servicename(snum);
5936
5937         /* Check the user has permissions to change the security
5938            descriptor.  By experimentation with two NT machines, the user
5939            requires Full Access to the printer to change security
5940            information. */
5941
5942         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5943                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5944                 result = WERR_ACCESS_DENIED;
5945                 goto done;
5946         }
5947
5948         result = winreg_printer_binding_handle(p->mem_ctx,
5949                                                get_session_info_system(),
5950                                                p->msg_ctx,
5951                                                &b);
5952         if (!W_ERROR_IS_OK(result)) {
5953                 goto done;
5954         }
5955
5956         /* NT seems to like setting the security descriptor even though
5957            nothing may have actually changed. */
5958         result = winreg_get_printer_secdesc(p->mem_ctx, b,
5959                                             printer,
5960                                             &old_secdesc);
5961         if (!W_ERROR_IS_OK(result)) {
5962                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5963                 result = WERR_BADFID;
5964                 goto done;
5965         }
5966
5967         if (DEBUGLEVEL >= 10) {
5968                 struct security_acl *the_acl;
5969                 int i;
5970
5971                 the_acl = old_secdesc->dacl;
5972                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5973                            printer, the_acl->num_aces));
5974
5975                 for (i = 0; i < the_acl->num_aces; i++) {
5976                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5977                                            &the_acl->aces[i].trustee),
5978                                   the_acl->aces[i].access_mask));
5979                 }
5980
5981                 the_acl = secdesc_ctr->sd->dacl;
5982
5983                 if (the_acl) {
5984                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5985                                    printer, the_acl->num_aces));
5986
5987                         for (i = 0; i < the_acl->num_aces; i++) {
5988                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5989                                                    &the_acl->aces[i].trustee),
5990                                            the_acl->aces[i].access_mask));
5991                         }
5992                 } else {
5993                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5994                 }
5995         }
5996
5997         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5998         if (new_secdesc == NULL) {
5999                 result = WERR_NOMEM;
6000                 goto done;
6001         }
6002
6003         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6004                 result = WERR_OK;
6005                 goto done;
6006         }
6007
6008         result = winreg_set_printer_secdesc(p->mem_ctx, b,
6009                                             printer,
6010                                             new_secdesc);
6011
6012  done:
6013         return result;
6014 }
6015
6016 /********************************************************************
6017  Canonicalize printer info from a client
6018  ********************************************************************/
6019
6020 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6021                              struct spoolss_SetPrinterInfo2 *info2,
6022                              int snum)
6023 {
6024         fstring printername;
6025         const char *p;
6026
6027         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6028                 "portname=%s drivername=%s comment=%s location=%s\n",
6029                 info2->servername, info2->printername, info2->sharename,
6030                 info2->portname, info2->drivername, info2->comment,
6031                 info2->location));
6032
6033         /* we force some elements to "correct" values */
6034         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6035         if (info2->servername == NULL) {
6036                 return false;
6037         }
6038         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6039         if (info2->sharename == NULL) {
6040                 return false;
6041         }
6042
6043         /* check to see if we allow printername != sharename */
6044         if (lp_force_printername(snum)) {
6045                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6046                                         global_myname(), info2->sharename);
6047         } else {
6048                 /* make sure printername is in \\server\printername format */
6049                 fstrcpy(printername, info2->printername);
6050                 p = printername;
6051                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6052                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6053                                 p++;
6054                 }
6055
6056                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6057                                         global_myname(), p);
6058         }
6059         if (info2->printername == NULL) {
6060                 return false;
6061         }
6062
6063         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6064         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6065
6066         return true;
6067 }
6068
6069 /****************************************************************************
6070 ****************************************************************************/
6071
6072 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6073 {
6074         char *cmd = lp_addport_cmd();
6075         char *command = NULL;
6076         int ret;
6077         bool is_print_op = false;
6078
6079         if ( !*cmd ) {
6080                 return WERR_ACCESS_DENIED;
6081         }
6082
6083         command = talloc_asprintf(ctx,
6084                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6085         if (!command) {
6086                 return WERR_NOMEM;
6087         }
6088
6089         if ( token )
6090                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6091
6092         DEBUG(10,("Running [%s]\n", command));
6093
6094         /********* BEGIN SePrintOperatorPrivilege **********/
6095
6096         if ( is_print_op )
6097                 become_root();
6098
6099         ret = smbrun(command, NULL);
6100
6101         if ( is_print_op )
6102                 unbecome_root();
6103
6104         /********* END SePrintOperatorPrivilege **********/
6105
6106         DEBUGADD(10,("returned [%d]\n", ret));
6107
6108         TALLOC_FREE(command);
6109
6110         if ( ret != 0 ) {
6111                 return WERR_ACCESS_DENIED;
6112         }
6113
6114         return WERR_OK;
6115 }
6116
6117 /****************************************************************************
6118 ****************************************************************************/
6119
6120 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6121                              struct spoolss_SetPrinterInfo2 *info2,
6122                              const char *remote_machine,
6123                              struct messaging_context *msg_ctx)
6124 {
6125         char *cmd = lp_addprinter_cmd();
6126         char **qlines;
6127         char *command = NULL;
6128         int numlines;
6129         int ret;
6130         int fd;
6131         bool is_print_op = false;
6132
6133         if (!remote_machine) {
6134                 return false;
6135         }
6136
6137         command = talloc_asprintf(ctx,
6138                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6139                         cmd, info2->printername, info2->sharename,
6140                         info2->portname, info2->drivername,
6141                         info2->location, info2->comment, remote_machine);
6142         if (!command) {
6143                 return false;
6144         }
6145
6146         if ( token )
6147                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6148
6149         DEBUG(10,("Running [%s]\n", command));
6150
6151         /********* BEGIN SePrintOperatorPrivilege **********/
6152
6153         if ( is_print_op )
6154                 become_root();
6155
6156         if ( (ret = smbrun(command, &fd)) == 0 ) {
6157                 /* Tell everyone we updated smb.conf. */
6158                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6159         }
6160
6161         if ( is_print_op )
6162                 unbecome_root();
6163
6164         /********* END SePrintOperatorPrivilege **********/
6165
6166         DEBUGADD(10,("returned [%d]\n", ret));
6167
6168         TALLOC_FREE(command);
6169
6170         if ( ret != 0 ) {
6171                 if (fd != -1)
6172                         close(fd);
6173                 return false;
6174         }
6175
6176         /* reload our services immediately */
6177         become_root();
6178         reload_services(msg_ctx, -1, false);
6179         unbecome_root();
6180
6181         numlines = 0;
6182         /* Get lines and convert them back to dos-codepage */
6183         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6184         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6185         close(fd);
6186
6187         /* Set the portname to what the script says the portname should be. */
6188         /* but don't require anything to be return from the script exit a good error code */
6189
6190         if (numlines) {
6191                 /* Set the portname to what the script says the portname should be. */
6192                 info2->portname = talloc_strdup(ctx, qlines[0]);
6193                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6194         }
6195
6196         TALLOC_FREE(qlines);
6197         return true;
6198 }
6199
6200 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6201                                const struct auth_serversupplied_info *session_info,
6202                                struct messaging_context *msg_ctx,
6203                                int snum,
6204                                struct spoolss_SetPrinterInfo2 *printer,
6205                                struct spoolss_PrinterInfo2 *old_printer)
6206 {
6207         bool force_update = (old_printer == NULL);
6208         const char *dnsdomname;
6209         const char *longname;
6210         const char *uncname;
6211         const char *spooling;
6212         DATA_BLOB buffer;
6213         WERROR result = WERR_OK;
6214         struct dcerpc_binding_handle *b;
6215
6216         result = winreg_printer_binding_handle(mem_ctx,
6217                                                session_info,
6218                                                msg_ctx,
6219                                                &b);
6220         if (!W_ERROR_IS_OK(result)) {
6221                 return result;
6222         }
6223
6224         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6225                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6226                 winreg_set_printer_dataex(mem_ctx, b,
6227                                           printer->sharename,
6228                                           SPOOL_DSSPOOLER_KEY,
6229                                           SPOOL_REG_DRIVERNAME,
6230                                           REG_SZ,
6231                                           buffer.data,
6232                                           buffer.length);
6233
6234                 if (!force_update) {
6235                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6236                                 printer->drivername));
6237
6238                         notify_printer_driver(server_event_context(), msg_ctx,
6239                                               snum, printer->drivername ?
6240                                               printer->drivername : "");
6241                 }
6242         }
6243
6244         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6245                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6246                 winreg_set_printer_dataex(mem_ctx, b,
6247                                           printer->sharename,
6248                                           SPOOL_DSSPOOLER_KEY,
6249                                           SPOOL_REG_DESCRIPTION,
6250                                           REG_SZ,
6251                                           buffer.data,
6252                                           buffer.length);
6253
6254                 if (!force_update) {
6255                         notify_printer_comment(server_event_context(), msg_ctx,
6256                                                snum, printer->comment ?
6257                                                printer->comment : "");
6258                 }
6259         }
6260
6261         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6262                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6263                 winreg_set_printer_dataex(mem_ctx, b,
6264                                           printer->sharename,
6265                                           SPOOL_DSSPOOLER_KEY,
6266                                           SPOOL_REG_PRINTSHARENAME,
6267                                           REG_SZ,
6268                                           buffer.data,
6269                                           buffer.length);
6270
6271                 if (!force_update) {
6272                         notify_printer_sharename(server_event_context(),
6273                                                  msg_ctx,
6274                                                  snum, printer->sharename ?
6275                                                  printer->sharename : "");
6276                 }
6277         }
6278
6279         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6280                 const char *p;
6281
6282                 p = strrchr(printer->printername, '\\' );
6283                 if (p != NULL) {
6284                         p++;
6285                 } else {
6286                         p = printer->printername;
6287                 }
6288
6289                 push_reg_sz(mem_ctx, &buffer, p);
6290                 winreg_set_printer_dataex(mem_ctx, b,
6291                                           printer->sharename,
6292                                           SPOOL_DSSPOOLER_KEY,
6293                                           SPOOL_REG_PRINTERNAME,
6294                                           REG_SZ,
6295                                           buffer.data,
6296                                           buffer.length);
6297
6298                 if (!force_update) {
6299                         notify_printer_printername(server_event_context(),
6300                                                    msg_ctx, snum, p ? p : "");
6301                 }
6302         }
6303
6304         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6305                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6306                 winreg_set_printer_dataex(mem_ctx, b,
6307                                           printer->sharename,
6308                                           SPOOL_DSSPOOLER_KEY,
6309                                           SPOOL_REG_PORTNAME,
6310                                           REG_SZ,
6311                                           buffer.data,
6312                                           buffer.length);
6313
6314                 if (!force_update) {
6315                         notify_printer_port(server_event_context(),
6316                                             msg_ctx, snum, printer->portname ?
6317                                             printer->portname : "");
6318                 }
6319         }
6320
6321         if (force_update || !strequal(printer->location, old_printer->location)) {
6322                 push_reg_sz(mem_ctx, &buffer, printer->location);
6323                 winreg_set_printer_dataex(mem_ctx, b,
6324                                           printer->sharename,
6325                                           SPOOL_DSSPOOLER_KEY,
6326                                           SPOOL_REG_LOCATION,
6327                                           REG_SZ,
6328                                           buffer.data,
6329                                           buffer.length);
6330
6331                 if (!force_update) {
6332                         notify_printer_location(server_event_context(),
6333                                                 msg_ctx, snum,
6334                                                 printer->location ?
6335                                                 printer->location : "");
6336                 }
6337         }
6338
6339         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6340                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6341                 winreg_set_printer_dataex(mem_ctx, b,
6342                                           printer->sharename,
6343                                           SPOOL_DSSPOOLER_KEY,
6344                                           SPOOL_REG_PRINTSEPARATORFILE,
6345                                           REG_SZ,
6346                                           buffer.data,
6347                                           buffer.length);
6348
6349                 if (!force_update) {
6350                         notify_printer_sepfile(server_event_context(),
6351                                                msg_ctx, snum,
6352                                                printer->sepfile ?
6353                                                printer->sepfile : "");
6354                 }
6355         }
6356
6357         if (force_update || printer->starttime != old_printer->starttime) {
6358                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6359                 SIVAL(buffer.data, 0, printer->starttime);
6360                 winreg_set_printer_dataex(mem_ctx, b,
6361                                           printer->sharename,
6362                                           SPOOL_DSSPOOLER_KEY,
6363                                           SPOOL_REG_PRINTSTARTTIME,
6364                                           REG_DWORD,
6365                                           buffer.data,
6366                                           buffer.length);
6367         }
6368
6369         if (force_update || printer->untiltime != old_printer->untiltime) {
6370                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6371                 SIVAL(buffer.data, 0, printer->untiltime);
6372                 winreg_set_printer_dataex(mem_ctx, b,
6373                                           printer->sharename,
6374                                           SPOOL_DSSPOOLER_KEY,
6375                                           SPOOL_REG_PRINTENDTIME,
6376                                           REG_DWORD,
6377                                           buffer.data,
6378                                           buffer.length);
6379         }
6380
6381         if (force_update || printer->priority != old_printer->priority) {
6382                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6383                 SIVAL(buffer.data, 0, printer->priority);
6384                 winreg_set_printer_dataex(mem_ctx, b,
6385                                           printer->sharename,
6386                                           SPOOL_DSSPOOLER_KEY,
6387                                           SPOOL_REG_PRIORITY,
6388                                           REG_DWORD,
6389                                           buffer.data,
6390                                           buffer.length);
6391         }
6392
6393         if (force_update || printer->attributes != old_printer->attributes) {
6394                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6395                 SIVAL(buffer.data, 0, (printer->attributes &
6396                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6397                 winreg_set_printer_dataex(mem_ctx, b,
6398                                           printer->sharename,
6399                                           SPOOL_DSSPOOLER_KEY,
6400                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6401                                           REG_DWORD,
6402                                           buffer.data,
6403                                           buffer.length);
6404
6405                 switch (printer->attributes & 0x3) {
6406                         case 0:
6407                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6408                                 break;
6409                         case 1:
6410                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6411                                 break;
6412                         case 2:
6413                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6414                                 break;
6415                         default:
6416                                 spooling = "unknown";
6417                 }
6418                 push_reg_sz(mem_ctx, &buffer, spooling);
6419                 winreg_set_printer_dataex(mem_ctx, b,
6420                                           printer->sharename,
6421                                           SPOOL_DSSPOOLER_KEY,
6422                                           SPOOL_REG_PRINTSPOOLING,
6423                                           REG_SZ,
6424                                           buffer.data,
6425                                           buffer.length);
6426         }
6427
6428         push_reg_sz(mem_ctx, &buffer, global_myname());
6429         winreg_set_printer_dataex(mem_ctx, b,
6430                                   printer->sharename,
6431                                   SPOOL_DSSPOOLER_KEY,
6432                                   SPOOL_REG_SHORTSERVERNAME,
6433                                   REG_SZ,
6434                                   buffer.data,
6435                                   buffer.length);
6436
6437         dnsdomname = get_mydnsfullname();
6438         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6439                 longname = talloc_strdup(mem_ctx, dnsdomname);
6440         } else {
6441                 longname = talloc_strdup(mem_ctx, global_myname());
6442         }
6443         if (longname == NULL) {
6444                 result = WERR_NOMEM;
6445                 goto done;
6446         }
6447
6448         push_reg_sz(mem_ctx, &buffer, longname);
6449         winreg_set_printer_dataex(mem_ctx, b,
6450                                   printer->sharename,
6451                                   SPOOL_DSSPOOLER_KEY,
6452                                   SPOOL_REG_SERVERNAME,
6453                                   REG_SZ,
6454                                   buffer.data,
6455                                   buffer.length);
6456
6457         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6458                                   global_myname(), printer->sharename);
6459         push_reg_sz(mem_ctx, &buffer, uncname);
6460         winreg_set_printer_dataex(mem_ctx, b,
6461                                   printer->sharename,
6462                                   SPOOL_DSSPOOLER_KEY,
6463                                   SPOOL_REG_UNCNAME,
6464                                   REG_SZ,
6465                                   buffer.data,
6466                                   buffer.length);
6467
6468 done:
6469         return result;
6470 }
6471
6472 /********************************************************************
6473  * Called by spoolss_api_setprinter
6474  * when updating a printer description.
6475  ********************************************************************/
6476
6477 static WERROR update_printer(struct pipes_struct *p,
6478                              struct policy_handle *handle,
6479                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6480                              struct spoolss_DeviceMode *devmode)
6481 {
6482         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6483         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6484         struct spoolss_PrinterInfo2 *old_printer;
6485         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6486         int snum;
6487         WERROR result = WERR_OK;
6488         TALLOC_CTX *tmp_ctx;
6489         struct dcerpc_binding_handle *b;
6490
6491         DEBUG(8,("update_printer\n"));
6492
6493         tmp_ctx = talloc_new(p->mem_ctx);
6494         if (tmp_ctx == NULL) {
6495                 return WERR_NOMEM;
6496         }
6497
6498         if (!Printer) {
6499                 result = WERR_BADFID;
6500                 goto done;
6501         }
6502
6503         if (!get_printer_snum(p, handle, &snum, NULL)) {
6504                 result = WERR_BADFID;
6505                 goto done;
6506         }
6507
6508         result = winreg_printer_binding_handle(tmp_ctx,
6509                                                get_session_info_system(),
6510                                                p->msg_ctx,
6511                                                &b);
6512         if (!W_ERROR_IS_OK(result)) {
6513                 goto done;
6514         }
6515
6516         result = winreg_get_printer(tmp_ctx, b,
6517                                     lp_const_servicename(snum),
6518                                     &old_printer);
6519         if (!W_ERROR_IS_OK(result)) {
6520                 result = WERR_BADFID;
6521                 goto done;
6522         }
6523
6524         /* Do sanity check on the requested changes for Samba */
6525         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6526                 result = WERR_INVALID_PARAM;
6527                 goto done;
6528         }
6529
6530         /* FIXME!!! If the driver has changed we really should verify that
6531            it is installed before doing much else   --jerry */
6532
6533         /* Check calling user has permission to update printer description */
6534         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6535                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6536                 result = WERR_ACCESS_DENIED;
6537                 goto done;
6538         }
6539
6540         /* Call addprinter hook */
6541         /* Check changes to see if this is really needed */
6542
6543         if (*lp_addprinter_cmd() &&
6544                         (!strequal(printer->drivername, old_printer->drivername) ||
6545                          !strequal(printer->comment, old_printer->comment) ||
6546                          !strequal(printer->portname, old_printer->portname) ||
6547                          !strequal(printer->location, old_printer->location)) )
6548         {
6549                 /* add_printer_hook() will call reload_services() */
6550                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6551                                       printer, p->client_id->addr,
6552                                       p->msg_ctx)) {
6553                         result = WERR_ACCESS_DENIED;
6554                         goto done;
6555                 }
6556         }
6557
6558         update_dsspooler(tmp_ctx,
6559                          get_session_info_system(),
6560                          p->msg_ctx,
6561                          snum,
6562                          printer,
6563                          old_printer);
6564
6565         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6566
6567         if (devmode == NULL) {
6568                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6569         }
6570         result = winreg_update_printer(tmp_ctx, b,
6571                                        printer->sharename,
6572                                        printer_mask,
6573                                        printer,
6574                                        devmode,
6575                                        NULL);
6576
6577 done:
6578         talloc_free(tmp_ctx);
6579
6580         return result;
6581 }
6582
6583 /****************************************************************************
6584 ****************************************************************************/
6585 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6586                                            struct policy_handle *handle,
6587                                            struct spoolss_SetPrinterInfo7 *info7)
6588 {
6589 #ifdef HAVE_ADS
6590         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6591         WERROR result;
6592         int snum;
6593         struct printer_handle *Printer;
6594
6595         if ( lp_security() != SEC_ADS ) {
6596                 return WERR_UNKNOWN_LEVEL;
6597         }
6598
6599         Printer = find_printer_index_by_hnd(p, handle);
6600
6601         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6602
6603         if (!Printer)
6604                 return WERR_BADFID;
6605
6606         if (!get_printer_snum(p, handle, &snum, NULL))
6607                 return WERR_BADFID;
6608
6609         result = winreg_get_printer_internal(p->mem_ctx,
6610                                     get_session_info_system(),
6611                                     p->msg_ctx,
6612                                     lp_servicename(snum),
6613                                     &pinfo2);
6614         if (!W_ERROR_IS_OK(result)) {
6615                 return WERR_BADFID;
6616         }
6617
6618         nt_printer_publish(pinfo2,
6619                            get_session_info_system(),
6620                            p->msg_ctx,
6621                            pinfo2,
6622                            info7->action);
6623
6624         TALLOC_FREE(pinfo2);
6625         return WERR_OK;
6626 #else
6627         return WERR_UNKNOWN_LEVEL;
6628 #endif
6629 }
6630
6631 /********************************************************************
6632  ********************************************************************/
6633
6634 static WERROR update_printer_devmode(struct pipes_struct *p,
6635                                      struct policy_handle *handle,
6636                                      struct spoolss_DeviceMode *devmode)
6637 {
6638         int snum;
6639         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6640         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6641
6642         DEBUG(8,("update_printer_devmode\n"));
6643
6644         if (!Printer) {
6645                 return WERR_BADFID;
6646         }
6647
6648         if (!get_printer_snum(p, handle, &snum, NULL)) {
6649                 return WERR_BADFID;
6650         }
6651
6652         /* Check calling user has permission to update printer description */
6653         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6654                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6655                 return WERR_ACCESS_DENIED;
6656         }
6657
6658         return winreg_update_printer_internal(p->mem_ctx,
6659                                      get_session_info_system(),
6660                                      p->msg_ctx,
6661                                      lp_const_servicename(snum),
6662                                      info2_mask,
6663                                      NULL,
6664                                      devmode,
6665                                      NULL);
6666 }
6667
6668
6669 /****************************************************************
6670  _spoolss_SetPrinter
6671 ****************************************************************/
6672
6673 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6674                            struct spoolss_SetPrinter *r)
6675 {
6676         WERROR result;
6677
6678         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6679
6680         if (!Printer) {
6681                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6682                         OUR_HANDLE(r->in.handle)));
6683                 return WERR_BADFID;
6684         }
6685
6686         /* check the level */
6687         switch (r->in.info_ctr->level) {
6688                 case 0:
6689                         return control_printer(r->in.handle, r->in.command, p);
6690                 case 2:
6691                         result = update_printer(p, r->in.handle,
6692                                                 r->in.info_ctr,
6693                                                 r->in.devmode_ctr->devmode);
6694                         if (!W_ERROR_IS_OK(result))
6695                                 return result;
6696                         if (r->in.secdesc_ctr->sd)
6697                                 result = update_printer_sec(r->in.handle, p,
6698                                                             r->in.secdesc_ctr);
6699                         return result;
6700                 case 3:
6701                         return update_printer_sec(r->in.handle, p,
6702                                                   r->in.secdesc_ctr);
6703                 case 7:
6704                         return publish_or_unpublish_printer(p, r->in.handle,
6705                                                             r->in.info_ctr->info.info7);
6706                 case 8:
6707                         return update_printer_devmode(p, r->in.handle,
6708                                                       r->in.devmode_ctr->devmode);
6709                 default:
6710                         return WERR_UNKNOWN_LEVEL;
6711         }
6712 }
6713
6714 /****************************************************************
6715  _spoolss_FindClosePrinterNotify
6716 ****************************************************************/
6717
6718 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6719                                        struct spoolss_FindClosePrinterNotify *r)
6720 {
6721         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6722
6723         if (!Printer) {
6724                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6725                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6726                 return WERR_BADFID;
6727         }
6728
6729         if (Printer->notify.cli_chan != NULL &&
6730             Printer->notify.cli_chan->active_connections > 0) {
6731                 int snum = -1;
6732
6733                 if (Printer->printer_type == SPLHND_PRINTER) {
6734                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6735                                 return WERR_BADFID;
6736                         }
6737                 }
6738
6739                 srv_spoolss_replycloseprinter(snum, Printer);
6740         }
6741
6742         Printer->notify.flags=0;
6743         Printer->notify.options=0;
6744         Printer->notify.localmachine[0]='\0';
6745         Printer->notify.printerlocal=0;
6746         TALLOC_FREE(Printer->notify.option);
6747
6748         return WERR_OK;
6749 }
6750
6751 /****************************************************************
6752  _spoolss_AddJob
6753 ****************************************************************/
6754
6755 WERROR _spoolss_AddJob(struct pipes_struct *p,
6756                        struct spoolss_AddJob *r)
6757 {
6758         if (!r->in.buffer && (r->in.offered != 0)) {
6759                 return WERR_INVALID_PARAM;
6760         }
6761
6762         /* this is what a NT server returns for AddJob. AddJob must fail on
6763          * non-local printers */
6764
6765         if (r->in.level != 1) {
6766                 return WERR_UNKNOWN_LEVEL;
6767         }
6768
6769         return WERR_INVALID_PARAM;
6770 }
6771
6772 /****************************************************************************
6773 fill_job_info1
6774 ****************************************************************************/
6775
6776 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6777                              struct spoolss_JobInfo1 *r,
6778                              const print_queue_struct *queue,
6779                              int position, int snum,
6780                              struct spoolss_PrinterInfo2 *pinfo2)
6781 {
6782         struct tm *t;
6783
6784         t = gmtime(&queue->time);
6785
6786         r->job_id               = queue->job;
6787
6788         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6789         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6790         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6791         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6792         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6793         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6794         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6795         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6796         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6797         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6798         r->text_status          = talloc_strdup(mem_ctx, "");
6799         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6800
6801         r->status               = nt_printj_status(queue->status);
6802         r->priority             = queue->priority;
6803         r->position             = position;
6804         r->total_pages          = queue->page_count;
6805         r->pages_printed        = 0; /* ??? */
6806
6807         init_systemtime(&r->submitted, t);
6808
6809         return WERR_OK;
6810 }
6811
6812 /****************************************************************************
6813 fill_job_info2
6814 ****************************************************************************/
6815
6816 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6817                              struct spoolss_JobInfo2 *r,
6818                              const print_queue_struct *queue,
6819                              int position, int snum,
6820                              struct spoolss_PrinterInfo2 *pinfo2,
6821                              struct spoolss_DeviceMode *devmode)
6822 {
6823         struct tm *t;
6824
6825         t = gmtime(&queue->time);
6826
6827         r->job_id               = queue->job;
6828
6829         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6830         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6831         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6832         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6833         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6834         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6835         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6836         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6837         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6838         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6839         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6840         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6841         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6842         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6843         r->parameters           = talloc_strdup(mem_ctx, "");
6844         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6845         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6846         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6847
6848         r->devmode              = devmode;
6849
6850         r->text_status          = talloc_strdup(mem_ctx, "");
6851         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6852
6853         r->secdesc              = NULL;
6854
6855         r->status               = nt_printj_status(queue->status);
6856         r->priority             = queue->priority;
6857         r->position             = position;
6858         r->start_time           = 0;
6859         r->until_time           = 0;
6860         r->total_pages          = queue->page_count;
6861         r->size                 = queue->size;
6862         init_systemtime(&r->submitted, t);
6863         r->time                 = 0;
6864         r->pages_printed        = 0; /* ??? */
6865
6866         return WERR_OK;
6867 }
6868
6869 /****************************************************************************
6870 fill_job_info3
6871 ****************************************************************************/
6872
6873 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6874                              struct spoolss_JobInfo3 *r,
6875                              const print_queue_struct *queue,
6876                              const print_queue_struct *next_queue,
6877                              int position, int snum,
6878                              struct spoolss_PrinterInfo2 *pinfo2)
6879 {
6880         r->job_id               = queue->job;
6881         r->next_job_id          = 0;
6882         if (next_queue) {
6883                 r->next_job_id  = next_queue->job;
6884         }
6885         r->reserved             = 0;
6886
6887         return WERR_OK;
6888 }
6889
6890 /****************************************************************************
6891  Enumjobs at level 1.
6892 ****************************************************************************/
6893
6894 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6895                               const print_queue_struct *queue,
6896                               uint32_t num_queues, int snum,
6897                               struct spoolss_PrinterInfo2 *pinfo2,
6898                               union spoolss_JobInfo **info_p,
6899                               uint32_t *count)
6900 {
6901         union spoolss_JobInfo *info;
6902         int i;
6903         WERROR result = WERR_OK;
6904
6905         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6906         W_ERROR_HAVE_NO_MEMORY(info);
6907
6908         *count = num_queues;
6909
6910         for (i=0; i<*count; i++) {
6911                 result = fill_job_info1(info,
6912                                         &info[i].info1,
6913                                         &queue[i],
6914                                         i,
6915                                         snum,
6916                                         pinfo2);
6917                 if (!W_ERROR_IS_OK(result)) {
6918                         goto out;
6919                 }
6920         }
6921
6922  out:
6923         if (!W_ERROR_IS_OK(result)) {
6924                 TALLOC_FREE(info);
6925                 *count = 0;
6926                 return result;
6927         }
6928
6929         *info_p = info;
6930
6931         return WERR_OK;
6932 }
6933
6934 /****************************************************************************
6935  Enumjobs at level 2.
6936 ****************************************************************************/
6937
6938 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6939                               const print_queue_struct *queue,
6940                               uint32_t num_queues, int snum,
6941                               struct spoolss_PrinterInfo2 *pinfo2,
6942                               union spoolss_JobInfo **info_p,
6943                               uint32_t *count)
6944 {
6945         union spoolss_JobInfo *info;
6946         int i;
6947         WERROR result = WERR_OK;
6948
6949         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6950         W_ERROR_HAVE_NO_MEMORY(info);
6951
6952         *count = num_queues;
6953
6954         for (i=0; i<*count; i++) {
6955                 struct spoolss_DeviceMode *devmode;
6956
6957                 result = spoolss_create_default_devmode(info,
6958                                                         pinfo2->printername,
6959                                                         &devmode);
6960                 if (!W_ERROR_IS_OK(result)) {
6961                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6962                         goto out;
6963                 }
6964
6965                 result = fill_job_info2(info,
6966                                         &info[i].info2,
6967                                         &queue[i],
6968                                         i,
6969                                         snum,
6970                                         pinfo2,
6971                                         devmode);
6972                 if (!W_ERROR_IS_OK(result)) {
6973                         goto out;
6974                 }
6975         }
6976
6977  out:
6978         if (!W_ERROR_IS_OK(result)) {
6979                 TALLOC_FREE(info);
6980                 *count = 0;
6981                 return result;
6982         }
6983
6984         *info_p = info;
6985
6986         return WERR_OK;
6987 }
6988
6989 /****************************************************************************
6990  Enumjobs at level 3.
6991 ****************************************************************************/
6992
6993 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6994                               const print_queue_struct *queue,
6995                               uint32_t num_queues, int snum,
6996                               struct spoolss_PrinterInfo2 *pinfo2,
6997                               union spoolss_JobInfo **info_p,
6998                               uint32_t *count)
6999 {
7000         union spoolss_JobInfo *info;
7001         int i;
7002         WERROR result = WERR_OK;
7003
7004         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7005         W_ERROR_HAVE_NO_MEMORY(info);
7006
7007         *count = num_queues;
7008
7009         for (i=0; i<*count; i++) {
7010                 const print_queue_struct *next_queue = NULL;
7011
7012                 if (i+1 < *count) {
7013                         next_queue = &queue[i+1];
7014                 }
7015
7016                 result = fill_job_info3(info,
7017                                         &info[i].info3,
7018                                         &queue[i],
7019                                         next_queue,
7020                                         i,
7021                                         snum,
7022                                         pinfo2);
7023                 if (!W_ERROR_IS_OK(result)) {
7024                         goto out;
7025                 }
7026         }
7027
7028  out:
7029         if (!W_ERROR_IS_OK(result)) {
7030                 TALLOC_FREE(info);
7031                 *count = 0;
7032                 return result;
7033         }
7034
7035         *info_p = info;
7036
7037         return WERR_OK;
7038 }
7039
7040 /****************************************************************
7041  _spoolss_EnumJobs
7042 ****************************************************************/
7043
7044 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7045                          struct spoolss_EnumJobs *r)
7046 {
7047         WERROR result;
7048         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7049         int snum;
7050         print_status_struct prt_status;
7051         print_queue_struct *queue = NULL;
7052         uint32_t count;
7053
7054         /* that's an [in out] buffer */
7055
7056         if (!r->in.buffer && (r->in.offered != 0)) {
7057                 return WERR_INVALID_PARAM;
7058         }
7059
7060         DEBUG(4,("_spoolss_EnumJobs\n"));
7061
7062         *r->out.needed = 0;
7063         *r->out.count = 0;
7064         *r->out.info = NULL;
7065
7066         /* lookup the printer snum and tdb entry */
7067
7068         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7069                 return WERR_BADFID;
7070         }
7071
7072         result = winreg_get_printer_internal(p->mem_ctx,
7073                                     get_session_info_system(),
7074                                     p->msg_ctx,
7075                                     lp_const_servicename(snum),
7076                                     &pinfo2);
7077         if (!W_ERROR_IS_OK(result)) {
7078                 return result;
7079         }
7080
7081         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7082         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7083                 count, prt_status.status, prt_status.message));
7084
7085         if (count == 0) {
7086                 SAFE_FREE(queue);
7087                 TALLOC_FREE(pinfo2);
7088                 return WERR_OK;
7089         }
7090
7091         switch (r->in.level) {
7092         case 1:
7093                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7094                                          pinfo2, r->out.info, r->out.count);
7095                 break;
7096         case 2:
7097                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7098                                          pinfo2, r->out.info, r->out.count);
7099                 break;
7100         case 3:
7101                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7102                                          pinfo2, r->out.info, r->out.count);
7103                 break;
7104         default:
7105                 result = WERR_UNKNOWN_LEVEL;
7106                 break;
7107         }
7108
7109         SAFE_FREE(queue);
7110         TALLOC_FREE(pinfo2);
7111
7112         if (!W_ERROR_IS_OK(result)) {
7113                 return result;
7114         }
7115
7116         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7117                                                      spoolss_EnumJobs,
7118                                                      *r->out.info, r->in.level,
7119                                                      *r->out.count);
7120         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7121         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7122
7123         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7124 }
7125
7126 /****************************************************************
7127  _spoolss_ScheduleJob
7128 ****************************************************************/
7129
7130 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7131                             struct spoolss_ScheduleJob *r)
7132 {
7133         return WERR_OK;
7134 }
7135
7136 /****************************************************************
7137 ****************************************************************/
7138
7139 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7140                                struct messaging_context *msg_ctx,
7141                                const char *printer_name,
7142                                uint32_t job_id,
7143                                struct spoolss_SetJobInfo1 *r)
7144 {
7145         char *old_doc_name;
7146
7147         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7148                 return WERR_BADFID;
7149         }
7150
7151         if (strequal(old_doc_name, r->document_name)) {
7152                 return WERR_OK;
7153         }
7154
7155         if (!print_job_set_name(server_event_context(), msg_ctx,
7156                                 printer_name, job_id, r->document_name)) {
7157                 return WERR_BADFID;
7158         }
7159
7160         return WERR_OK;
7161 }
7162
7163 /****************************************************************
7164  _spoolss_SetJob
7165 ****************************************************************/
7166
7167 WERROR _spoolss_SetJob(struct pipes_struct *p,
7168                        struct spoolss_SetJob *r)
7169 {
7170         const struct auth_serversupplied_info *session_info = p->session_info;
7171         int snum;
7172         WERROR errcode = WERR_BADFUNC;
7173
7174         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7175                 return WERR_BADFID;
7176         }
7177
7178         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7179                 return WERR_INVALID_PRINTER_NAME;
7180         }
7181
7182         switch (r->in.command) {
7183         case SPOOLSS_JOB_CONTROL_CANCEL:
7184         case SPOOLSS_JOB_CONTROL_DELETE:
7185                 errcode = print_job_delete(session_info, p->msg_ctx,
7186                                            snum, r->in.job_id);
7187                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7188                         errcode = WERR_OK;
7189                 }
7190                 break;
7191         case SPOOLSS_JOB_CONTROL_PAUSE:
7192                 if (print_job_pause(session_info, p->msg_ctx,
7193                                     snum, r->in.job_id, &errcode)) {
7194                         errcode = WERR_OK;
7195                 }
7196                 break;
7197         case SPOOLSS_JOB_CONTROL_RESTART:
7198         case SPOOLSS_JOB_CONTROL_RESUME:
7199                 if (print_job_resume(session_info, p->msg_ctx,
7200                                      snum, r->in.job_id, &errcode)) {
7201                         errcode = WERR_OK;
7202                 }
7203                 break;
7204         case 0:
7205                 errcode = WERR_OK;
7206                 break;
7207         default:
7208                 return WERR_UNKNOWN_LEVEL;
7209         }
7210
7211         if (!W_ERROR_IS_OK(errcode)) {
7212                 return errcode;
7213         }
7214
7215         if (r->in.ctr == NULL) {
7216                 return errcode;
7217         }
7218
7219         switch (r->in.ctr->level) {
7220         case 1:
7221                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7222                                            lp_const_servicename(snum),
7223                                            r->in.job_id,
7224                                            r->in.ctr->info.info1);
7225                 break;
7226         case 2:
7227         case 3:
7228         case 4:
7229         default:
7230                 return WERR_UNKNOWN_LEVEL;
7231         }
7232
7233         return errcode;
7234 }
7235
7236 /****************************************************************************
7237  Enumerates all printer drivers by level and architecture.
7238 ****************************************************************************/
7239
7240 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7241                                                        const struct auth_serversupplied_info *session_info,
7242                                                        struct messaging_context *msg_ctx,
7243                                                        const char *servername,
7244                                                        const char *architecture,
7245                                                        uint32_t level,
7246                                                        union spoolss_DriverInfo **info_p,
7247                                                        uint32_t *count_p)
7248 {
7249         int i;
7250         uint32_t version;
7251         struct spoolss_DriverInfo8 *driver;
7252         union spoolss_DriverInfo *info = NULL;
7253         uint32_t count = 0;
7254         WERROR result = WERR_OK;
7255         uint32_t num_drivers;
7256         const char **drivers;
7257         struct dcerpc_binding_handle *b;
7258
7259         *count_p = 0;
7260         *info_p = NULL;
7261
7262         result = winreg_printer_binding_handle(mem_ctx,
7263                                                session_info,
7264                                                msg_ctx,
7265                                                &b);
7266         if (!W_ERROR_IS_OK(result)) {
7267                 goto out;
7268         }
7269
7270         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7271                 result = winreg_get_driver_list(mem_ctx, b,
7272                                                 architecture, version,
7273                                                 &num_drivers, &drivers);
7274                 if (!W_ERROR_IS_OK(result)) {
7275                         goto out;
7276                 }
7277                 DEBUG(4, ("we have:[%d] drivers in environment"
7278                           " [%s] and version [%d]\n",
7279                           num_drivers, architecture, version));
7280
7281                 if (num_drivers != 0) {
7282                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7283                                                     union spoolss_DriverInfo,
7284                                                     count + num_drivers);
7285                         if (!info) {
7286                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7287                                         "failed to enlarge driver info buffer!\n"));
7288                                 result = WERR_NOMEM;
7289                                 goto out;
7290                         }
7291                 }
7292
7293                 for (i = 0; i < num_drivers; i++) {
7294                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7295
7296                         result = winreg_get_driver(mem_ctx, b,
7297                                                    architecture, drivers[i],
7298                                                    version, &driver);
7299                         if (!W_ERROR_IS_OK(result)) {
7300                                 goto out;
7301                         }
7302
7303                         switch (level) {
7304                         case 1:
7305                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7306                                                                    driver, servername);
7307                                 break;
7308                         case 2:
7309                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7310                                                                    driver, servername);
7311                                 break;
7312                         case 3:
7313                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7314                                                                    driver, servername);
7315                                 break;
7316                         case 4:
7317                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7318                                                                    driver, servername);
7319                                 break;
7320                         case 5:
7321                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7322                                                                    driver, servername);
7323                                 break;
7324                         case 6:
7325                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7326                                                                    driver, servername);
7327                                 break;
7328                         case 8:
7329                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7330                                                                    driver, servername);
7331                                 break;
7332                         default:
7333                                 result = WERR_UNKNOWN_LEVEL;
7334                                 break;
7335                         }
7336
7337                         TALLOC_FREE(driver);
7338
7339                         if (!W_ERROR_IS_OK(result)) {
7340                                 goto out;
7341                         }
7342                 }
7343
7344                 count += num_drivers;
7345                 TALLOC_FREE(drivers);
7346         }
7347
7348  out:
7349         TALLOC_FREE(drivers);
7350
7351         if (!W_ERROR_IS_OK(result)) {
7352                 TALLOC_FREE(info);
7353                 return result;
7354         }
7355
7356         *info_p = info;
7357         *count_p = count;
7358
7359         return WERR_OK;
7360 }
7361
7362 /****************************************************************************
7363  Enumerates all printer drivers by level.
7364 ****************************************************************************/
7365
7366 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7367                                        const struct auth_serversupplied_info *session_info,
7368                                        struct messaging_context *msg_ctx,
7369                                        const char *servername,
7370                                        const char *architecture,
7371                                        uint32_t level,
7372                                        union spoolss_DriverInfo **info_p,
7373                                        uint32_t *count_p)
7374 {
7375         uint32_t a,i;
7376         WERROR result = WERR_OK;
7377
7378         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7379
7380                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7381
7382                         union spoolss_DriverInfo *info = NULL;
7383                         uint32_t count = 0;
7384
7385                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7386                                                                           session_info,
7387                                                                           msg_ctx,
7388                                                                           servername,
7389                                                                           archi_table[a].long_archi,
7390                                                                           level,
7391                                                                           &info,
7392                                                                           &count);
7393                         if (!W_ERROR_IS_OK(result)) {
7394                                 continue;
7395                         }
7396
7397                         for (i=0; i < count; i++) {
7398                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7399                                              info[i], info_p, count_p);
7400                         }
7401                 }
7402
7403                 return result;
7404         }
7405
7406         return enumprinterdrivers_level_by_architecture(mem_ctx,
7407                                                         session_info,
7408                                                         msg_ctx,
7409                                                         servername,
7410                                                         architecture,
7411                                                         level,
7412                                                         info_p,
7413                                                         count_p);
7414 }
7415
7416 /****************************************************************
7417  _spoolss_EnumPrinterDrivers
7418 ****************************************************************/
7419
7420 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7421                                    struct spoolss_EnumPrinterDrivers *r)
7422 {
7423         const char *cservername;
7424         WERROR result;
7425
7426         /* that's an [in out] buffer */
7427
7428         if (!r->in.buffer && (r->in.offered != 0)) {
7429                 return WERR_INVALID_PARAM;
7430         }
7431
7432         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7433
7434         *r->out.needed = 0;
7435         *r->out.count = 0;
7436         *r->out.info = NULL;
7437
7438         cservername = canon_servername(r->in.server);
7439
7440         if (!is_myname_or_ipaddr(cservername)) {
7441                 return WERR_UNKNOWN_PRINTER_DRIVER;
7442         }
7443
7444         result = enumprinterdrivers_level(p->mem_ctx,
7445                                           get_session_info_system(),
7446                                           p->msg_ctx,
7447                                           cservername,
7448                                           r->in.environment,
7449                                           r->in.level,
7450                                           r->out.info,
7451                                           r->out.count);
7452         if (!W_ERROR_IS_OK(result)) {
7453                 return result;
7454         }
7455
7456         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7457                                                      spoolss_EnumPrinterDrivers,
7458                                                      *r->out.info, r->in.level,
7459                                                      *r->out.count);
7460         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7461         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7462
7463         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7464 }
7465
7466 /****************************************************************
7467  _spoolss_EnumForms
7468 ****************************************************************/
7469
7470 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7471                           struct spoolss_EnumForms *r)
7472 {
7473         WERROR result;
7474
7475         *r->out.count = 0;
7476         *r->out.needed = 0;
7477         *r->out.info = NULL;
7478
7479         /* that's an [in out] buffer */
7480
7481         if (!r->in.buffer && (r->in.offered != 0) ) {
7482                 return WERR_INVALID_PARAM;
7483         }
7484
7485         DEBUG(4,("_spoolss_EnumForms\n"));
7486         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7487         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7488
7489         switch (r->in.level) {
7490         case 1:
7491                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7492                                                    get_session_info_system(),
7493                                                    p->msg_ctx,
7494                                                    r->out.count,
7495                                                    r->out.info);
7496                 break;
7497         default:
7498                 result = WERR_UNKNOWN_LEVEL;
7499                 break;
7500         }
7501
7502         if (!W_ERROR_IS_OK(result)) {
7503                 return result;
7504         }
7505
7506         if (*r->out.count == 0) {
7507                 return WERR_NO_MORE_ITEMS;
7508         }
7509
7510         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7511                                                      spoolss_EnumForms,
7512                                                      *r->out.info, r->in.level,
7513                                                      *r->out.count);
7514         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7515         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7516
7517         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7518 }
7519
7520 /****************************************************************
7521  _spoolss_GetForm
7522 ****************************************************************/
7523
7524 WERROR _spoolss_GetForm(struct pipes_struct *p,
7525                         struct spoolss_GetForm *r)
7526 {
7527         WERROR result;
7528
7529         /* that's an [in out] buffer */
7530
7531         if (!r->in.buffer && (r->in.offered != 0)) {
7532                 return WERR_INVALID_PARAM;
7533         }
7534
7535         DEBUG(4,("_spoolss_GetForm\n"));
7536         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7537         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7538
7539         switch (r->in.level) {
7540         case 1:
7541                 result = winreg_printer_getform1_internal(p->mem_ctx,
7542                                                  get_session_info_system(),
7543                                                  p->msg_ctx,
7544                                                  r->in.form_name,
7545                                                  &r->out.info->info1);
7546                 break;
7547         default:
7548                 result = WERR_UNKNOWN_LEVEL;
7549                 break;
7550         }
7551
7552         if (!W_ERROR_IS_OK(result)) {
7553                 TALLOC_FREE(r->out.info);
7554                 return result;
7555         }
7556
7557         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7558                                                r->out.info, r->in.level);
7559         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7560
7561         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7562 }
7563
7564 /****************************************************************************
7565 ****************************************************************************/
7566
7567 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7568                           struct spoolss_PortInfo1 *r,
7569                           const char *name)
7570 {
7571         r->port_name = talloc_strdup(mem_ctx, name);
7572         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7573
7574         return WERR_OK;
7575 }
7576
7577 /****************************************************************************
7578  TODO: This probably needs distinguish between TCP/IP and Local ports
7579  somehow.
7580 ****************************************************************************/
7581
7582 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7583                           struct spoolss_PortInfo2 *r,
7584                           const char *name)
7585 {
7586         r->port_name = talloc_strdup(mem_ctx, name);
7587         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7588
7589         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7590         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7591
7592         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7593         W_ERROR_HAVE_NO_MEMORY(r->description);
7594
7595         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7596         r->reserved = 0;
7597
7598         return WERR_OK;
7599 }
7600
7601
7602 /****************************************************************************
7603  wrapper around the enumer ports command
7604 ****************************************************************************/
7605
7606 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7607 {
7608         char *cmd = lp_enumports_cmd();
7609         char **qlines = NULL;
7610         char *command = NULL;
7611         int numlines;
7612         int ret;
7613         int fd;
7614
7615         *count = 0;
7616         *lines = NULL;
7617
7618         /* if no hook then just fill in the default port */
7619
7620         if ( !*cmd ) {
7621                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7622                         return WERR_NOMEM;
7623                 }
7624                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7625                         TALLOC_FREE(qlines);
7626                         return WERR_NOMEM;
7627                 }
7628                 qlines[1] = NULL;
7629                 numlines = 1;
7630         }
7631         else {
7632                 /* we have a valid enumport command */
7633
7634                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7635                 if (!command) {
7636                         return WERR_NOMEM;
7637                 }
7638
7639                 DEBUG(10,("Running [%s]\n", command));
7640                 ret = smbrun(command, &fd);
7641                 DEBUG(10,("Returned [%d]\n", ret));
7642                 TALLOC_FREE(command);
7643                 if (ret != 0) {
7644                         if (fd != -1) {
7645                                 close(fd);
7646                         }
7647                         return WERR_ACCESS_DENIED;
7648                 }
7649
7650                 numlines = 0;
7651                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7652                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7653                 close(fd);
7654         }
7655
7656         *count = numlines;
7657         *lines = qlines;
7658
7659         return WERR_OK;
7660 }
7661
7662 /****************************************************************************
7663  enumports level 1.
7664 ****************************************************************************/
7665
7666 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7667                                 union spoolss_PortInfo **info_p,
7668                                 uint32_t *count)
7669 {
7670         union spoolss_PortInfo *info = NULL;
7671         int i=0;
7672         WERROR result = WERR_OK;
7673         char **qlines = NULL;
7674         int numlines = 0;
7675
7676         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7677         if (!W_ERROR_IS_OK(result)) {
7678                 goto out;
7679         }
7680
7681         if (numlines) {
7682                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7683                 if (!info) {
7684                         DEBUG(10,("Returning WERR_NOMEM\n"));
7685                         result = WERR_NOMEM;
7686                         goto out;
7687                 }
7688
7689                 for (i=0; i<numlines; i++) {
7690                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7691                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7692                         if (!W_ERROR_IS_OK(result)) {
7693                                 goto out;
7694                         }
7695                 }
7696         }
7697         TALLOC_FREE(qlines);
7698
7699 out:
7700         if (!W_ERROR_IS_OK(result)) {
7701                 TALLOC_FREE(info);
7702                 TALLOC_FREE(qlines);
7703                 *count = 0;
7704                 *info_p = NULL;
7705                 return result;
7706         }
7707
7708         *info_p = info;
7709         *count = numlines;
7710
7711         return WERR_OK;
7712 }
7713
7714 /****************************************************************************
7715  enumports level 2.
7716 ****************************************************************************/
7717
7718 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7719                                 union spoolss_PortInfo **info_p,
7720                                 uint32_t *count)
7721 {
7722         union spoolss_PortInfo *info = NULL;
7723         int i=0;
7724         WERROR result = WERR_OK;
7725         char **qlines = NULL;
7726         int numlines = 0;
7727
7728         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7729         if (!W_ERROR_IS_OK(result)) {
7730                 goto out;
7731         }
7732
7733         if (numlines) {
7734                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7735                 if (!info) {
7736                         DEBUG(10,("Returning WERR_NOMEM\n"));
7737                         result = WERR_NOMEM;
7738                         goto out;
7739                 }
7740
7741                 for (i=0; i<numlines; i++) {
7742                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7743                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7744                         if (!W_ERROR_IS_OK(result)) {
7745                                 goto out;
7746                         }
7747                 }
7748         }
7749         TALLOC_FREE(qlines);
7750
7751 out:
7752         if (!W_ERROR_IS_OK(result)) {
7753                 TALLOC_FREE(info);
7754                 TALLOC_FREE(qlines);
7755                 *count = 0;
7756                 *info_p = NULL;
7757                 return result;
7758         }
7759
7760         *info_p = info;
7761         *count = numlines;
7762
7763         return WERR_OK;
7764 }
7765
7766 /****************************************************************
7767  _spoolss_EnumPorts
7768 ****************************************************************/
7769
7770 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7771                           struct spoolss_EnumPorts *r)
7772 {
7773         WERROR result;
7774
7775         /* that's an [in out] buffer */
7776
7777         if (!r->in.buffer && (r->in.offered != 0)) {
7778                 return WERR_INVALID_PARAM;
7779         }
7780
7781         DEBUG(4,("_spoolss_EnumPorts\n"));
7782
7783         *r->out.count = 0;
7784         *r->out.needed = 0;
7785         *r->out.info = NULL;
7786
7787         switch (r->in.level) {
7788         case 1:
7789                 result = enumports_level_1(p->mem_ctx, r->out.info,
7790                                            r->out.count);
7791                 break;
7792         case 2:
7793                 result = enumports_level_2(p->mem_ctx, r->out.info,
7794                                            r->out.count);
7795                 break;
7796         default:
7797                 return WERR_UNKNOWN_LEVEL;
7798         }
7799
7800         if (!W_ERROR_IS_OK(result)) {
7801                 return result;
7802         }
7803
7804         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7805                                                      spoolss_EnumPorts,
7806                                                      *r->out.info, r->in.level,
7807                                                      *r->out.count);
7808         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7809         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7810
7811         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7812 }
7813
7814 /****************************************************************************
7815 ****************************************************************************/
7816
7817 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7818                                            const char *server,
7819                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7820                                            struct spoolss_DeviceMode *devmode,
7821                                            struct security_descriptor *secdesc,
7822                                            struct spoolss_UserLevelCtr *user_ctr,
7823                                            struct policy_handle *handle)
7824 {
7825         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7826         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7827         int     snum;
7828         WERROR err = WERR_OK;
7829
7830         /* samba does not have a concept of local, non-shared printers yet, so
7831          * make sure we always setup sharename - gd */
7832         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7833             (info2->printername != NULL && info2->printername[0] != '\0')) {
7834                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7835                         "no sharename has been set, setting printername %s as sharename\n",
7836                         info2->printername));
7837                 info2->sharename = info2->printername;
7838         }
7839
7840         /* check to see if the printer already exists */
7841         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7842                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7843                         info2->sharename));
7844                 return WERR_PRINTER_ALREADY_EXISTS;
7845         }
7846
7847         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7848                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7849                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7850                                 info2->printername));
7851                         return WERR_PRINTER_ALREADY_EXISTS;
7852                 }
7853         }
7854
7855         /* validate printer info struct */
7856         if (!info2->printername || strlen(info2->printername) == 0) {
7857                 return WERR_INVALID_PRINTER_NAME;
7858         }
7859         if (!info2->portname || strlen(info2->portname) == 0) {
7860                 return WERR_UNKNOWN_PORT;
7861         }
7862         if (!info2->drivername || strlen(info2->drivername) == 0) {
7863                 return WERR_UNKNOWN_PRINTER_DRIVER;
7864         }
7865         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7866                 return WERR_UNKNOWN_PRINTPROCESSOR;
7867         }
7868
7869         /* FIXME!!!  smbd should check to see if the driver is installed before
7870            trying to add a printer like this  --jerry */
7871
7872         if (*lp_addprinter_cmd() ) {
7873                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7874                                        info2, p->client_id->addr,
7875                                        p->msg_ctx) ) {
7876                         return WERR_ACCESS_DENIED;
7877                 }
7878         } else {
7879                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7880                         "smb.conf parameter \"addprinter command\" is defined. This "
7881                         "parameter must exist for this call to succeed\n",
7882                         info2->sharename ));
7883         }
7884
7885         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7886                 return WERR_ACCESS_DENIED;
7887         }
7888
7889         /* you must be a printer admin to add a new printer */
7890         if (!print_access_check(p->session_info,
7891                                 p->msg_ctx,
7892                                 snum,
7893                                 PRINTER_ACCESS_ADMINISTER)) {
7894                 return WERR_ACCESS_DENIED;
7895         }
7896
7897         /*
7898          * Do sanity check on the requested changes for Samba.
7899          */
7900
7901         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7902                 return WERR_INVALID_PARAM;
7903         }
7904
7905         if (devmode == NULL) {
7906                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7907         }
7908
7909         update_dsspooler(p->mem_ctx,
7910                          get_session_info_system(),
7911                          p->msg_ctx,
7912                          0,
7913                          info2,
7914                          NULL);
7915
7916         err = winreg_update_printer_internal(p->mem_ctx,
7917                                     get_session_info_system(),
7918                                     p->msg_ctx,
7919                                     info2->sharename,
7920                                     info2_mask,
7921                                     info2,
7922                                     devmode,
7923                                     secdesc);
7924         if (!W_ERROR_IS_OK(err)) {
7925                 return err;
7926         }
7927
7928         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7929         if (!W_ERROR_IS_OK(err)) {
7930                 /* Handle open failed - remove addition. */
7931                 ZERO_STRUCTP(handle);
7932                 return err;
7933         }
7934
7935         return WERR_OK;
7936 }
7937
7938 /****************************************************************
7939  _spoolss_AddPrinterEx
7940 ****************************************************************/
7941
7942 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7943                              struct spoolss_AddPrinterEx *r)
7944 {
7945         switch (r->in.info_ctr->level) {
7946         case 1:
7947                 /* we don't handle yet */
7948                 /* but I know what to do ... */
7949                 return WERR_UNKNOWN_LEVEL;
7950         case 2:
7951                 return spoolss_addprinterex_level_2(p, r->in.server,
7952                                                     r->in.info_ctr,
7953                                                     r->in.devmode_ctr->devmode,
7954                                                     r->in.secdesc_ctr->sd,
7955                                                     r->in.userlevel_ctr,
7956                                                     r->out.handle);
7957         default:
7958                 return WERR_UNKNOWN_LEVEL;
7959         }
7960 }
7961
7962 /****************************************************************
7963  _spoolss_AddPrinter
7964 ****************************************************************/
7965
7966 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7967                            struct spoolss_AddPrinter *r)
7968 {
7969         struct spoolss_AddPrinterEx a;
7970         struct spoolss_UserLevelCtr userlevel_ctr;
7971
7972         ZERO_STRUCT(userlevel_ctr);
7973
7974         userlevel_ctr.level = 1;
7975
7976         a.in.server             = r->in.server;
7977         a.in.info_ctr           = r->in.info_ctr;
7978         a.in.devmode_ctr        = r->in.devmode_ctr;
7979         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7980         a.in.userlevel_ctr      = &userlevel_ctr;
7981         a.out.handle            = r->out.handle;
7982
7983         return _spoolss_AddPrinterEx(p, &a);
7984 }
7985
7986 /****************************************************************
7987  _spoolss_AddPrinterDriverEx
7988 ****************************************************************/
7989
7990 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7991                                    struct spoolss_AddPrinterDriverEx *r)
7992 {
7993         WERROR err = WERR_OK;
7994         const char *driver_name = NULL;
7995         uint32_t version;
7996         const char *fn;
7997
7998         switch (p->opnum) {
7999                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8000                         fn = "_spoolss_AddPrinterDriver";
8001                         break;
8002                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8003                         fn = "_spoolss_AddPrinterDriverEx";
8004                         break;
8005                 default:
8006                         return WERR_INVALID_PARAM;
8007         }
8008
8009         /*
8010          * we only support the semantics of AddPrinterDriver()
8011          * i.e. only copy files that are newer than existing ones
8012          */
8013
8014         if (r->in.flags == 0) {
8015                 return WERR_INVALID_PARAM;
8016         }
8017
8018         if (r->in.flags != APD_COPY_NEW_FILES) {
8019                 return WERR_ACCESS_DENIED;
8020         }
8021
8022         /* FIXME */
8023         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8024                 /* Clever hack from Martin Zielinski <mz@seh.de>
8025                  * to allow downgrade from level 8 (Vista).
8026                  */
8027                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8028                         r->in.info_ctr->level));
8029                 return WERR_UNKNOWN_LEVEL;
8030         }
8031
8032         DEBUG(5,("Cleaning driver's information\n"));
8033         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8034         if (!W_ERROR_IS_OK(err))
8035                 goto done;
8036
8037         DEBUG(5,("Moving driver to final destination\n"));
8038         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8039         if (!W_ERROR_IS_OK(err)) {
8040                 goto done;
8041         }
8042
8043         err = winreg_add_driver_internal(p->mem_ctx,
8044                                 get_session_info_system(),
8045                                 p->msg_ctx,
8046                                 r->in.info_ctr,
8047                                 &driver_name,
8048                                 &version);
8049         if (!W_ERROR_IS_OK(err)) {
8050                 goto done;
8051         }
8052
8053         /*
8054          * I think this is where he DrvUpgradePrinter() hook would be
8055          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8056          * server.  Right now, we just need to send ourselves a message
8057          * to update each printer bound to this driver.   --jerry
8058          */
8059
8060         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8061                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8062                         fn, driver_name));
8063         }
8064
8065 done:
8066         return err;
8067 }
8068
8069 /****************************************************************
8070  _spoolss_AddPrinterDriver
8071 ****************************************************************/
8072
8073 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8074                                  struct spoolss_AddPrinterDriver *r)
8075 {
8076         struct spoolss_AddPrinterDriverEx a;
8077
8078         switch (r->in.info_ctr->level) {
8079         case 2:
8080         case 3:
8081         case 4:
8082         case 5:
8083                 break;
8084         default:
8085                 return WERR_UNKNOWN_LEVEL;
8086         }
8087
8088         a.in.servername         = r->in.servername;
8089         a.in.info_ctr           = r->in.info_ctr;
8090         a.in.flags              = APD_COPY_NEW_FILES;
8091
8092         return _spoolss_AddPrinterDriverEx(p, &a);
8093 }
8094
8095 /****************************************************************************
8096 ****************************************************************************/
8097
8098 struct _spoolss_paths {
8099         int type;
8100         const char *share;
8101         const char *dir;
8102 };
8103
8104 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8105
8106 static const struct _spoolss_paths spoolss_paths[]= {
8107         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8108         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8109 };
8110
8111 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8112                                           const char *servername,
8113                                           const char *environment,
8114                                           int component,
8115                                           char **path)
8116 {
8117         const char *pservername = NULL;
8118         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8119         const char *short_archi;
8120
8121         *path = NULL;
8122
8123         /* environment may be empty */
8124         if (environment && strlen(environment)) {
8125                 long_archi = environment;
8126         }
8127
8128         /* servername may be empty */
8129         if (servername && strlen(servername)) {
8130                 pservername = canon_servername(servername);
8131
8132                 if (!is_myname_or_ipaddr(pservername)) {
8133                         return WERR_INVALID_PARAM;
8134                 }
8135         }
8136
8137         if (!(short_archi = get_short_archi(long_archi))) {
8138                 return WERR_INVALID_ENVIRONMENT;
8139         }
8140
8141         switch (component) {
8142         case SPOOLSS_PRTPROCS_PATH:
8143         case SPOOLSS_DRIVER_PATH:
8144                 if (pservername) {
8145                         *path = talloc_asprintf(mem_ctx,
8146                                         "\\\\%s\\%s\\%s",
8147                                         pservername,
8148                                         spoolss_paths[component].share,
8149                                         short_archi);
8150                 } else {
8151                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8152                                         SPOOLSS_DEFAULT_SERVER_PATH,
8153                                         spoolss_paths[component].dir,
8154                                         short_archi);
8155                 }
8156                 break;
8157         default:
8158                 return WERR_INVALID_PARAM;
8159         }
8160
8161         if (!*path) {
8162                 return WERR_NOMEM;
8163         }
8164
8165         return WERR_OK;
8166 }
8167
8168 /****************************************************************************
8169 ****************************************************************************/
8170
8171 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8172                                           const char *servername,
8173                                           const char *environment,
8174                                           struct spoolss_DriverDirectoryInfo1 *r)
8175 {
8176         WERROR werr;
8177         char *path = NULL;
8178
8179         werr = compose_spoolss_server_path(mem_ctx,
8180                                            servername,
8181                                            environment,
8182                                            SPOOLSS_DRIVER_PATH,
8183                                            &path);
8184         if (!W_ERROR_IS_OK(werr)) {
8185                 return werr;
8186         }
8187
8188         DEBUG(4,("printer driver directory: [%s]\n", path));
8189
8190         r->directory_name = path;
8191
8192         return WERR_OK;
8193 }
8194
8195 /****************************************************************
8196  _spoolss_GetPrinterDriverDirectory
8197 ****************************************************************/
8198
8199 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8200                                           struct spoolss_GetPrinterDriverDirectory *r)
8201 {
8202         WERROR werror;
8203
8204         /* that's an [in out] buffer */
8205
8206         if (!r->in.buffer && (r->in.offered != 0)) {
8207                 return WERR_INVALID_PARAM;
8208         }
8209
8210         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8211                 r->in.level));
8212
8213         *r->out.needed = 0;
8214
8215         /* r->in.level is ignored */
8216
8217         werror = getprinterdriverdir_level_1(p->mem_ctx,
8218                                              r->in.server,
8219                                              r->in.environment,
8220                                              &r->out.info->info1);
8221         if (!W_ERROR_IS_OK(werror)) {
8222                 TALLOC_FREE(r->out.info);
8223                 return werror;
8224         }
8225
8226         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8227                                                r->out.info, r->in.level);
8228         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8229
8230         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8231 }
8232
8233 /****************************************************************
8234  _spoolss_EnumPrinterData
8235 ****************************************************************/
8236
8237 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8238                                 struct spoolss_EnumPrinterData *r)
8239 {
8240         WERROR result;
8241         struct spoolss_EnumPrinterDataEx r2;
8242         uint32_t count;
8243         struct spoolss_PrinterEnumValues *info, *val = NULL;
8244         uint32_t needed;
8245
8246         r2.in.handle    = r->in.handle;
8247         r2.in.key_name  = "PrinterDriverData";
8248         r2.in.offered   = 0;
8249         r2.out.count    = &count;
8250         r2.out.info     = &info;
8251         r2.out.needed   = &needed;
8252
8253         result = _spoolss_EnumPrinterDataEx(p, &r2);
8254         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8255                 r2.in.offered = needed;
8256                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8257         }
8258         if (!W_ERROR_IS_OK(result)) {
8259                 return result;
8260         }
8261
8262         /*
8263          * The NT machine wants to know the biggest size of value and data
8264          *
8265          * cf: MSDN EnumPrinterData remark section
8266          */
8267
8268         if (!r->in.value_offered && !r->in.data_offered) {
8269                 uint32_t biggest_valuesize = 0;
8270                 uint32_t biggest_datasize = 0;
8271                 int i, name_length;
8272
8273                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8274
8275                 for (i=0; i<count; i++) {
8276
8277                         name_length = strlen(info[i].value_name);
8278                         if (strlen(info[i].value_name) > biggest_valuesize) {
8279                                 biggest_valuesize = name_length;
8280                         }
8281
8282                         if (info[i].data_length > biggest_datasize) {
8283                                 biggest_datasize = info[i].data_length;
8284                         }
8285
8286                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8287                                 biggest_datasize));
8288                 }
8289
8290                 /* the value is an UNICODE string but real_value_size is the length
8291                    in bytes including the trailing 0 */
8292
8293                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8294                 *r->out.data_needed  = biggest_datasize;
8295
8296                 DEBUG(6,("final values: [%d], [%d]\n",
8297                         *r->out.value_needed, *r->out.data_needed));
8298
8299                 return WERR_OK;
8300         }
8301
8302         if (r->in.enum_index < count) {
8303                 val = &info[r->in.enum_index];
8304         }
8305
8306         if (val == NULL) {
8307                 /* out_value should default to "" or else NT4 has
8308                    problems unmarshalling the response */
8309
8310                 if (r->in.value_offered) {
8311                         *r->out.value_needed = 1;
8312                         r->out.value_name = talloc_strdup(r, "");
8313                         if (!r->out.value_name) {
8314                                 return WERR_NOMEM;
8315                         }
8316                 } else {
8317                         r->out.value_name = NULL;
8318                         *r->out.value_needed = 0;
8319                 }
8320
8321                 /* the data is counted in bytes */
8322
8323                 *r->out.data_needed = r->in.data_offered;
8324
8325                 result = WERR_NO_MORE_ITEMS;
8326         } else {
8327                 /*
8328                  * the value is:
8329                  * - counted in bytes in the request
8330                  * - counted in UNICODE chars in the max reply
8331                  * - counted in bytes in the real size
8332                  *
8333                  * take a pause *before* coding not *during* coding
8334                  */
8335
8336                 /* name */
8337                 if (r->in.value_offered) {
8338                         r->out.value_name = talloc_strdup(r, val->value_name);
8339                         if (!r->out.value_name) {
8340                                 return WERR_NOMEM;
8341                         }
8342                         *r->out.value_needed = val->value_name_len;
8343                 } else {
8344                         r->out.value_name = NULL;
8345                         *r->out.value_needed = 0;
8346                 }
8347
8348                 /* type */
8349
8350                 *r->out.type = val->type;
8351
8352                 /* data - counted in bytes */
8353
8354                 /*
8355                  * See the section "Dynamically Typed Query Parameters"
8356                  * in MS-RPRN.
8357                  */
8358
8359                 if (r->out.data && val->data && val->data->data &&
8360                                 val->data_length && r->in.data_offered) {
8361                         memcpy(r->out.data, val->data->data,
8362                                 MIN(val->data_length,r->in.data_offered));
8363                 }
8364
8365                 *r->out.data_needed = val->data_length;
8366
8367                 result = WERR_OK;
8368         }
8369
8370         return result;
8371 }
8372
8373 /****************************************************************
8374  _spoolss_SetPrinterData
8375 ****************************************************************/
8376
8377 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8378                                struct spoolss_SetPrinterData *r)
8379 {
8380         struct spoolss_SetPrinterDataEx r2;
8381
8382         r2.in.handle            = r->in.handle;
8383         r2.in.key_name          = "PrinterDriverData";
8384         r2.in.value_name        = r->in.value_name;
8385         r2.in.type              = r->in.type;
8386         r2.in.data              = r->in.data;
8387         r2.in.offered           = r->in.offered;
8388
8389         return _spoolss_SetPrinterDataEx(p, &r2);
8390 }
8391
8392 /****************************************************************
8393  _spoolss_ResetPrinter
8394 ****************************************************************/
8395
8396 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8397                              struct spoolss_ResetPrinter *r)
8398 {
8399         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8400         int             snum;
8401
8402         DEBUG(5,("_spoolss_ResetPrinter\n"));
8403
8404         /*
8405          * All we do is to check to see if the handle and queue is valid.
8406          * This call really doesn't mean anything to us because we only
8407          * support RAW printing.   --jerry
8408          */
8409
8410         if (!Printer) {
8411                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8412                         OUR_HANDLE(r->in.handle)));
8413                 return WERR_BADFID;
8414         }
8415
8416         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8417                 return WERR_BADFID;
8418
8419
8420         /* blindly return success */
8421         return WERR_OK;
8422 }
8423
8424 /****************************************************************
8425  _spoolss_DeletePrinterData
8426 ****************************************************************/
8427
8428 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8429                                   struct spoolss_DeletePrinterData *r)
8430 {
8431         struct spoolss_DeletePrinterDataEx r2;
8432
8433         r2.in.handle            = r->in.handle;
8434         r2.in.key_name          = "PrinterDriverData";
8435         r2.in.value_name        = r->in.value_name;
8436
8437         return _spoolss_DeletePrinterDataEx(p, &r2);
8438 }
8439
8440 /****************************************************************
8441  _spoolss_AddForm
8442 ****************************************************************/
8443
8444 WERROR _spoolss_AddForm(struct pipes_struct *p,
8445                         struct spoolss_AddForm *r)
8446 {
8447         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8448         int snum = -1;
8449         WERROR status = WERR_OK;
8450         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8451         struct dcerpc_binding_handle *b;
8452
8453         DEBUG(5,("_spoolss_AddForm\n"));
8454
8455         if (!Printer) {
8456                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8457                         OUR_HANDLE(r->in.handle)));
8458                 return WERR_BADFID;
8459         }
8460
8461         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8462            and not a printer admin, then fail */
8463
8464         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8465             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8466             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8467                                           p->session_info->info3->base.domain.string,
8468                                           NULL,
8469                                           p->session_info->security_token,
8470                                           lp_printer_admin(snum))) {
8471                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8472                 return WERR_ACCESS_DENIED;
8473         }
8474
8475         switch (form->flags) {
8476         case SPOOLSS_FORM_USER:
8477         case SPOOLSS_FORM_BUILTIN:
8478         case SPOOLSS_FORM_PRINTER:
8479                 break;
8480         default:
8481                 return WERR_INVALID_PARAM;
8482         }
8483
8484         status = winreg_printer_binding_handle(p->mem_ctx,
8485                                                get_session_info_system(),
8486                                                p->msg_ctx,
8487                                                &b);
8488         if (!W_ERROR_IS_OK(status)) {
8489                 return status;
8490         }
8491
8492         status = winreg_printer_addform1(p->mem_ctx, b,
8493                                          form);
8494         if (!W_ERROR_IS_OK(status)) {
8495                 return status;
8496         }
8497
8498         /*
8499          * ChangeID must always be set if this is a printer
8500          */
8501         if (Printer->printer_type == SPLHND_PRINTER) {
8502                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8503                         return WERR_BADFID;
8504                 }
8505
8506                 status = winreg_printer_update_changeid(p->mem_ctx, b,
8507                                                         lp_const_servicename(snum));
8508                 if (!W_ERROR_IS_OK(status)) {
8509                         return status;
8510                 }
8511         }
8512
8513         return status;
8514 }
8515
8516 /****************************************************************
8517  _spoolss_DeleteForm
8518 ****************************************************************/
8519
8520 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8521                            struct spoolss_DeleteForm *r)
8522 {
8523         const char *form_name = r->in.form_name;
8524         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8525         int snum = -1;
8526         WERROR status = WERR_OK;
8527         struct dcerpc_binding_handle *b;
8528
8529         DEBUG(5,("_spoolss_DeleteForm\n"));
8530
8531         if (!Printer) {
8532                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8533                         OUR_HANDLE(r->in.handle)));
8534                 return WERR_BADFID;
8535         }
8536
8537         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8538             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8539             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8540                                           p->session_info->info3->base.domain.string,
8541                                           NULL,
8542                                           p->session_info->security_token,
8543                                           lp_printer_admin(snum))) {
8544                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8545                 return WERR_ACCESS_DENIED;
8546         }
8547
8548         status = winreg_printer_binding_handle(p->mem_ctx,
8549                                                get_session_info_system(),
8550                                                p->msg_ctx,
8551                                                &b);
8552         if (!W_ERROR_IS_OK(status)) {
8553                 return status;
8554         }
8555
8556         status = winreg_printer_deleteform1(p->mem_ctx, b,
8557                                             form_name);
8558         if (!W_ERROR_IS_OK(status)) {
8559                 return status;
8560         }
8561
8562         /*
8563          * ChangeID must always be set if this is a printer
8564          */
8565         if (Printer->printer_type == SPLHND_PRINTER) {
8566                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8567                         return WERR_BADFID;
8568                 }
8569
8570                 status = winreg_printer_update_changeid(p->mem_ctx, b,
8571                                                         lp_const_servicename(snum));
8572                 if (!W_ERROR_IS_OK(status)) {
8573                         return status;
8574                 }
8575         }
8576
8577         return status;
8578 }
8579
8580 /****************************************************************
8581  _spoolss_SetForm
8582 ****************************************************************/
8583
8584 WERROR _spoolss_SetForm(struct pipes_struct *p,
8585                         struct spoolss_SetForm *r)
8586 {
8587         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8588         const char *form_name = r->in.form_name;
8589         int snum = -1;
8590         WERROR status = WERR_OK;
8591         struct dcerpc_binding_handle *b;
8592
8593         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8594
8595         DEBUG(5,("_spoolss_SetForm\n"));
8596
8597         if (!Printer) {
8598                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8599                         OUR_HANDLE(r->in.handle)));
8600                 return WERR_BADFID;
8601         }
8602
8603         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8604            and not a printer admin, then fail */
8605
8606         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8607              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8608              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8609                                           p->session_info->info3->base.domain.string,
8610                                           NULL,
8611                                           p->session_info->security_token,
8612                                           lp_printer_admin(snum))) {
8613                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8614                 return WERR_ACCESS_DENIED;
8615         }
8616
8617         status = winreg_printer_binding_handle(p->mem_ctx,
8618                                                get_session_info_system(),
8619                                                p->msg_ctx,
8620                                                &b);
8621         if (!W_ERROR_IS_OK(status)) {
8622                 return status;
8623         }
8624
8625         status = winreg_printer_setform1(p->mem_ctx, b,
8626                                          form_name,
8627                                          form);
8628         if (!W_ERROR_IS_OK(status)) {
8629                 return status;
8630         }
8631
8632         /*
8633          * ChangeID must always be set if this is a printer
8634          */
8635         if (Printer->printer_type == SPLHND_PRINTER) {
8636                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8637                         return WERR_BADFID;
8638                 }
8639
8640                 status = winreg_printer_update_changeid(p->mem_ctx, b,
8641                                                         lp_const_servicename(snum));
8642                 if (!W_ERROR_IS_OK(status)) {
8643                         return status;
8644                 }
8645         }
8646
8647         return status;
8648 }
8649
8650 /****************************************************************************
8651  fill_print_processor1
8652 ****************************************************************************/
8653
8654 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8655                                     struct spoolss_PrintProcessorInfo1 *r,
8656                                     const char *print_processor_name)
8657 {
8658         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8659         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8660
8661         return WERR_OK;
8662 }
8663
8664 /****************************************************************************
8665  enumprintprocessors level 1.
8666 ****************************************************************************/
8667
8668 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8669                                           union spoolss_PrintProcessorInfo **info_p,
8670                                           uint32_t *count)
8671 {
8672         union spoolss_PrintProcessorInfo *info;
8673         WERROR result;
8674
8675         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8676         W_ERROR_HAVE_NO_MEMORY(info);
8677
8678         *count = 1;
8679
8680         result = fill_print_processor1(info, &info[0].info1, "winprint");
8681         if (!W_ERROR_IS_OK(result)) {
8682                 goto out;
8683         }
8684
8685  out:
8686         if (!W_ERROR_IS_OK(result)) {
8687                 TALLOC_FREE(info);
8688                 *count = 0;
8689                 return result;
8690         }
8691
8692         *info_p = info;
8693
8694         return WERR_OK;
8695 }
8696
8697 /****************************************************************
8698  _spoolss_EnumPrintProcessors
8699 ****************************************************************/
8700
8701 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8702                                     struct spoolss_EnumPrintProcessors *r)
8703 {
8704         WERROR result;
8705
8706         /* that's an [in out] buffer */
8707
8708         if (!r->in.buffer && (r->in.offered != 0)) {
8709                 return WERR_INVALID_PARAM;
8710         }
8711
8712         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8713
8714         /*
8715          * Enumerate the print processors ...
8716          *
8717          * Just reply with "winprint", to keep NT happy
8718          * and I can use my nice printer checker.
8719          */
8720
8721         *r->out.count = 0;
8722         *r->out.needed = 0;
8723         *r->out.info = NULL;
8724
8725         if (!get_short_archi(r->in.environment)) {
8726                 return WERR_INVALID_ENVIRONMENT;
8727         }
8728
8729         switch (r->in.level) {
8730         case 1:
8731                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8732                                                      r->out.count);
8733                 break;
8734         default:
8735                 return WERR_UNKNOWN_LEVEL;
8736         }
8737
8738         if (!W_ERROR_IS_OK(result)) {
8739                 return result;
8740         }
8741
8742         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8743                                                      spoolss_EnumPrintProcessors,
8744                                                      *r->out.info, r->in.level,
8745                                                      *r->out.count);
8746         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8747         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8748
8749         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8750 }
8751
8752 /****************************************************************************
8753  fill_printprocdatatype1
8754 ****************************************************************************/
8755
8756 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8757                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8758                                       const char *name_array)
8759 {
8760         r->name_array = talloc_strdup(mem_ctx, name_array);
8761         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8762
8763         return WERR_OK;
8764 }
8765
8766 /****************************************************************************
8767  enumprintprocdatatypes level 1.
8768 ****************************************************************************/
8769
8770 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8771                                              union spoolss_PrintProcDataTypesInfo **info_p,
8772                                              uint32_t *count)
8773 {
8774         WERROR result;
8775         union spoolss_PrintProcDataTypesInfo *info;
8776
8777         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8778         W_ERROR_HAVE_NO_MEMORY(info);
8779
8780         *count = 1;
8781
8782         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8783         if (!W_ERROR_IS_OK(result)) {
8784                 goto out;
8785         }
8786
8787  out:
8788         if (!W_ERROR_IS_OK(result)) {
8789                 TALLOC_FREE(info);
8790                 *count = 0;
8791                 return result;
8792         }
8793
8794         *info_p = info;
8795
8796         return WERR_OK;
8797 }
8798
8799 /****************************************************************
8800  _spoolss_EnumPrintProcDataTypes
8801 ****************************************************************/
8802
8803 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8804                                        struct spoolss_EnumPrintProcDataTypes *r)
8805 {
8806         WERROR result;
8807
8808         /* that's an [in out] buffer */
8809
8810         if (!r->in.buffer && (r->in.offered != 0)) {
8811                 return WERR_INVALID_PARAM;
8812         }
8813
8814         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8815
8816         *r->out.count = 0;
8817         *r->out.needed = 0;
8818         *r->out.info = NULL;
8819
8820         if (r->in.print_processor_name == NULL ||
8821             !strequal(r->in.print_processor_name, "winprint")) {
8822                 return WERR_UNKNOWN_PRINTPROCESSOR;
8823         }
8824
8825         switch (r->in.level) {
8826         case 1:
8827                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8828                                                         r->out.count);
8829                 break;
8830         default:
8831                 return WERR_UNKNOWN_LEVEL;
8832         }
8833
8834         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8835                                                      spoolss_EnumPrintProcDataTypes,
8836                                                      *r->out.info, r->in.level,
8837                                                      *r->out.count);
8838         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8839         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8840
8841         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8842 }
8843
8844 /****************************************************************************
8845  fill_monitor_1
8846 ****************************************************************************/
8847
8848 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8849                              struct spoolss_MonitorInfo1 *r,
8850                              const char *monitor_name)
8851 {
8852         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8853         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8854
8855         return WERR_OK;
8856 }
8857
8858 /****************************************************************************
8859  fill_monitor_2
8860 ****************************************************************************/
8861
8862 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8863                              struct spoolss_MonitorInfo2 *r,
8864                              const char *monitor_name,
8865                              const char *environment,
8866                              const char *dll_name)
8867 {
8868         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8869         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8870         r->environment                  = talloc_strdup(mem_ctx, environment);
8871         W_ERROR_HAVE_NO_MEMORY(r->environment);
8872         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8873         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8874
8875         return WERR_OK;
8876 }
8877
8878 /****************************************************************************
8879  enumprintmonitors level 1.
8880 ****************************************************************************/
8881
8882 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8883                                         union spoolss_MonitorInfo **info_p,
8884                                         uint32_t *count)
8885 {
8886         union spoolss_MonitorInfo *info;
8887         WERROR result = WERR_OK;
8888
8889         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8890         W_ERROR_HAVE_NO_MEMORY(info);
8891
8892         *count = 2;
8893
8894         result = fill_monitor_1(info, &info[0].info1,
8895                                 SPL_LOCAL_PORT);
8896         if (!W_ERROR_IS_OK(result)) {
8897                 goto out;
8898         }
8899
8900         result = fill_monitor_1(info, &info[1].info1,
8901                                 SPL_TCPIP_PORT);
8902         if (!W_ERROR_IS_OK(result)) {
8903                 goto out;
8904         }
8905
8906 out:
8907         if (!W_ERROR_IS_OK(result)) {
8908                 TALLOC_FREE(info);
8909                 *count = 0;
8910                 return result;
8911         }
8912
8913         *info_p = info;
8914
8915         return WERR_OK;
8916 }
8917
8918 /****************************************************************************
8919  enumprintmonitors level 2.
8920 ****************************************************************************/
8921
8922 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8923                                         union spoolss_MonitorInfo **info_p,
8924                                         uint32_t *count)
8925 {
8926         union spoolss_MonitorInfo *info;
8927         WERROR result = WERR_OK;
8928
8929         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8930         W_ERROR_HAVE_NO_MEMORY(info);
8931
8932         *count = 2;
8933
8934         result = fill_monitor_2(info, &info[0].info2,
8935                                 SPL_LOCAL_PORT,
8936                                 "Windows NT X86", /* FIXME */
8937                                 "localmon.dll");
8938         if (!W_ERROR_IS_OK(result)) {
8939                 goto out;
8940         }
8941
8942         result = fill_monitor_2(info, &info[1].info2,
8943                                 SPL_TCPIP_PORT,
8944                                 "Windows NT X86", /* FIXME */
8945                                 "tcpmon.dll");
8946         if (!W_ERROR_IS_OK(result)) {
8947                 goto out;
8948         }
8949
8950 out:
8951         if (!W_ERROR_IS_OK(result)) {
8952                 TALLOC_FREE(info);
8953                 *count = 0;
8954                 return result;
8955         }
8956
8957         *info_p = info;
8958
8959         return WERR_OK;
8960 }
8961
8962 /****************************************************************
8963  _spoolss_EnumMonitors
8964 ****************************************************************/
8965
8966 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8967                              struct spoolss_EnumMonitors *r)
8968 {
8969         WERROR result;
8970
8971         /* that's an [in out] buffer */
8972
8973         if (!r->in.buffer && (r->in.offered != 0)) {
8974                 return WERR_INVALID_PARAM;
8975         }
8976
8977         DEBUG(5,("_spoolss_EnumMonitors\n"));
8978
8979         /*
8980          * Enumerate the print monitors ...
8981          *
8982          * Just reply with "Local Port", to keep NT happy
8983          * and I can use my nice printer checker.
8984          */
8985
8986         *r->out.count = 0;
8987         *r->out.needed = 0;
8988         *r->out.info = NULL;
8989
8990         switch (r->in.level) {
8991         case 1:
8992                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8993                                                    r->out.count);
8994                 break;
8995         case 2:
8996                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8997                                                    r->out.count);
8998                 break;
8999         default:
9000                 return WERR_UNKNOWN_LEVEL;
9001         }
9002
9003         if (!W_ERROR_IS_OK(result)) {
9004                 return result;
9005         }
9006
9007         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9008                                                      spoolss_EnumMonitors,
9009                                                      *r->out.info, r->in.level,
9010                                                      *r->out.count);
9011         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9012         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9013
9014         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9015 }
9016
9017 /****************************************************************************
9018 ****************************************************************************/
9019
9020 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9021                              const print_queue_struct *queue,
9022                              int count, int snum,
9023                              struct spoolss_PrinterInfo2 *pinfo2,
9024                              uint32_t jobid,
9025                              struct spoolss_JobInfo1 *r)
9026 {
9027         int i = 0;
9028         bool found = false;
9029
9030         for (i=0; i<count; i++) {
9031                 if (queue[i].job == (int)jobid) {
9032                         found = true;
9033                         break;
9034                 }
9035         }
9036
9037         if (found == false) {
9038                 /* NT treats not found as bad param... yet another bad choice */
9039                 return WERR_INVALID_PARAM;
9040         }
9041
9042         return fill_job_info1(mem_ctx,
9043                               r,
9044                               &queue[i],
9045                               i,
9046                               snum,
9047                               pinfo2);
9048 }
9049
9050 /****************************************************************************
9051 ****************************************************************************/
9052
9053 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9054                              const print_queue_struct *queue,
9055                              int count, int snum,
9056                              struct spoolss_PrinterInfo2 *pinfo2,
9057                              uint32_t jobid,
9058                              struct spoolss_JobInfo2 *r)
9059 {
9060         int i = 0;
9061         bool found = false;
9062         struct spoolss_DeviceMode *devmode;
9063         WERROR result;
9064
9065         for (i=0; i<count; i++) {
9066                 if (queue[i].job == (int)jobid) {
9067                         found = true;
9068                         break;
9069                 }
9070         }
9071
9072         if (found == false) {
9073                 /* NT treats not found as bad param... yet another bad
9074                    choice */
9075                 return WERR_INVALID_PARAM;
9076         }
9077
9078         /*
9079          * if the print job does not have a DEVMODE associated with it,
9080          * just use the one for the printer. A NULL devicemode is not
9081          *  a failure condition
9082          */
9083
9084         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9085         if (!devmode) {
9086                 result = spoolss_create_default_devmode(mem_ctx,
9087                                                 pinfo2->printername,
9088                                                 &devmode);
9089                 if (!W_ERROR_IS_OK(result)) {
9090                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9091                         return result;
9092                 }
9093         }
9094
9095         return fill_job_info2(mem_ctx,
9096                               r,
9097                               &queue[i],
9098                               i,
9099                               snum,
9100                               pinfo2,
9101                               devmode);
9102 }
9103
9104 /****************************************************************
9105  _spoolss_GetJob
9106 ****************************************************************/
9107
9108 WERROR _spoolss_GetJob(struct pipes_struct *p,
9109                        struct spoolss_GetJob *r)
9110 {
9111         WERROR result = WERR_OK;
9112         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9113         int snum;
9114         int count;
9115         print_queue_struct      *queue = NULL;
9116         print_status_struct prt_status;
9117
9118         /* that's an [in out] buffer */
9119
9120         if (!r->in.buffer && (r->in.offered != 0)) {
9121                 return WERR_INVALID_PARAM;
9122         }
9123
9124         DEBUG(5,("_spoolss_GetJob\n"));
9125
9126         *r->out.needed = 0;
9127
9128         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9129                 return WERR_BADFID;
9130         }
9131
9132         result = winreg_get_printer_internal(p->mem_ctx,
9133                                     get_session_info_system(),
9134                                     p->msg_ctx,
9135                                     lp_const_servicename(snum),
9136                                     &pinfo2);
9137         if (!W_ERROR_IS_OK(result)) {
9138                 return result;
9139         }
9140
9141         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9142
9143         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9144                      count, prt_status.status, prt_status.message));
9145
9146         switch (r->in.level) {
9147         case 1:
9148                 result = getjob_level_1(p->mem_ctx,
9149                                         queue, count, snum, pinfo2,
9150                                         r->in.job_id, &r->out.info->info1);
9151                 break;
9152         case 2:
9153                 result = getjob_level_2(p->mem_ctx,
9154                                         queue, count, snum, pinfo2,
9155                                         r->in.job_id, &r->out.info->info2);
9156                 break;
9157         default:
9158                 result = WERR_UNKNOWN_LEVEL;
9159                 break;
9160         }
9161
9162         SAFE_FREE(queue);
9163         TALLOC_FREE(pinfo2);
9164
9165         if (!W_ERROR_IS_OK(result)) {
9166                 TALLOC_FREE(r->out.info);
9167                 return result;
9168         }
9169
9170         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9171                                                                                    r->in.level);
9172         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9173
9174         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9175 }
9176
9177 /****************************************************************
9178  _spoolss_GetPrinterDataEx
9179 ****************************************************************/
9180
9181 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9182                                  struct spoolss_GetPrinterDataEx *r)
9183 {
9184
9185         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9186         const char *printer;
9187         int                     snum = 0;
9188         WERROR result = WERR_OK;
9189         DATA_BLOB blob;
9190         enum winreg_Type val_type = REG_NONE;
9191         uint8_t *val_data = NULL;
9192         uint32_t val_size = 0;
9193         struct dcerpc_binding_handle *b;
9194
9195         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9196
9197         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9198                 r->in.key_name, r->in.value_name));
9199
9200         /* in case of problem, return some default values */
9201
9202         *r->out.needed  = 0;
9203         *r->out.type    = REG_NONE;
9204
9205         if (!Printer) {
9206                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9207                         OUR_HANDLE(r->in.handle)));
9208                 result = WERR_BADFID;
9209                 goto done;
9210         }
9211
9212         /* Is the handle to a printer or to the server? */
9213
9214         if (Printer->printer_type == SPLHND_SERVER) {
9215
9216                 union spoolss_PrinterData data;
9217
9218                 result = getprinterdata_printer_server(p->mem_ctx,
9219                                                        r->in.value_name,
9220                                                        r->out.type,
9221                                                        &data);
9222                 if (!W_ERROR_IS_OK(result)) {
9223                         return result;
9224                 }
9225
9226                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9227                                                   *r->out.type, &data);
9228                 if (!W_ERROR_IS_OK(result)) {
9229                         return result;
9230                 }
9231
9232                 *r->out.needed = blob.length;
9233
9234                 if (r->in.offered >= *r->out.needed) {
9235                         memcpy(r->out.data, blob.data, blob.length);
9236                 }
9237
9238                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9239         }
9240
9241         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9242                 return WERR_BADFID;
9243         }
9244         printer = lp_const_servicename(snum);
9245
9246         /* check to see if the keyname is valid */
9247         if (!strlen(r->in.key_name)) {
9248                 return WERR_INVALID_PARAM;
9249         }
9250
9251         result = winreg_printer_binding_handle(p->mem_ctx,
9252                                                get_session_info_system(),
9253                                                p->msg_ctx,
9254                                                &b);
9255         if (!W_ERROR_IS_OK(result)) {
9256                 return result;
9257         }
9258
9259         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9260         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9261             strequal(r->in.value_name, "ChangeId")) {
9262                 *r->out.type = REG_DWORD;
9263                 *r->out.needed = 4;
9264                 if (r->in.offered >= *r->out.needed) {
9265                         uint32_t changeid = 0;
9266
9267                         result = winreg_printer_get_changeid(p->mem_ctx, b,
9268                                                              printer,
9269                                                              &changeid);
9270                         if (!W_ERROR_IS_OK(result)) {
9271                                 return result;
9272                         }
9273
9274                         SIVAL(r->out.data, 0, changeid);
9275                         result = WERR_OK;
9276                 }
9277                 goto done;
9278         }
9279
9280         result = winreg_get_printer_dataex(p->mem_ctx, b,
9281                                            printer,
9282                                            r->in.key_name,
9283                                            r->in.value_name,
9284                                            &val_type,
9285                                            &val_data,
9286                                            &val_size);
9287         if (!W_ERROR_IS_OK(result)) {
9288                 return result;
9289         }
9290
9291         *r->out.needed = val_size;
9292         *r->out.type = val_type;
9293
9294         if (r->in.offered >= *r->out.needed) {
9295                 memcpy(r->out.data, val_data, val_size);
9296         }
9297
9298  done:
9299         /* retain type when returning WERR_MORE_DATA */
9300         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9301
9302         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9303 }
9304
9305 /****************************************************************
9306  _spoolss_SetPrinterDataEx
9307 ****************************************************************/
9308
9309 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9310                                  struct spoolss_SetPrinterDataEx *r)
9311 {
9312         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9313         int                     snum = 0;
9314         WERROR                  result = WERR_OK;
9315         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9316         char                    *oid_string;
9317         struct dcerpc_binding_handle *b;
9318
9319         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9320
9321         /* From MSDN documentation of SetPrinterDataEx: pass request to
9322            SetPrinterData if key is "PrinterDriverData" */
9323
9324         if (!Printer) {
9325                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9326                         OUR_HANDLE(r->in.handle)));
9327                 return WERR_BADFID;
9328         }
9329
9330         if (Printer->printer_type == SPLHND_SERVER) {
9331                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9332                         "Not implemented for server handles yet\n"));
9333                 return WERR_INVALID_PARAM;
9334         }
9335
9336         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9337                 return WERR_BADFID;
9338         }
9339
9340         /*
9341          * Access check : NT returns "access denied" if you make a
9342          * SetPrinterData call without the necessary privildge.
9343          * we were originally returning OK if nothing changed
9344          * which made Win2k issue **a lot** of SetPrinterData
9345          * when connecting to a printer  --jerry
9346          */
9347
9348         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9349                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9350                         "change denied by handle access permissions\n"));
9351                 return WERR_ACCESS_DENIED;
9352         }
9353
9354         result = winreg_printer_binding_handle(p->mem_ctx,
9355                                                get_session_info_system(),
9356                                                p->msg_ctx,
9357                                                &b);
9358         if (!W_ERROR_IS_OK(result)) {
9359                 return result;
9360         }
9361
9362         result = winreg_get_printer(Printer, b,
9363                                     lp_servicename(snum),
9364                                     &pinfo2);
9365         if (!W_ERROR_IS_OK(result)) {
9366                 return result;
9367         }
9368
9369         /* check for OID in valuename */
9370
9371         oid_string = strchr(r->in.value_name, ',');
9372         if (oid_string) {
9373                 *oid_string = '\0';
9374                 oid_string++;
9375         }
9376
9377         /* save the registry data */
9378
9379         result = winreg_set_printer_dataex(p->mem_ctx, b,
9380                                            pinfo2->sharename,
9381                                            r->in.key_name,
9382                                            r->in.value_name,
9383                                            r->in.type,
9384                                            r->in.data,
9385                                            r->in.offered);
9386
9387         if (W_ERROR_IS_OK(result)) {
9388                 /* save the OID if one was specified */
9389                 if (oid_string) {
9390                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9391                                 r->in.key_name, SPOOL_OID_KEY);
9392                         if (!str) {
9393                                 result = WERR_NOMEM;
9394                                 goto done;
9395                         }
9396
9397                         /*
9398                          * I'm not checking the status here on purpose.  Don't know
9399                          * if this is right, but I'm returning the status from the
9400                          * previous set_printer_dataex() call.  I have no idea if
9401                          * this is right.    --jerry
9402                          */
9403                         winreg_set_printer_dataex(p->mem_ctx, b,
9404                                                   pinfo2->sharename,
9405                                                   str,
9406                                                   r->in.value_name,
9407                                                   REG_SZ,
9408                                                   (uint8_t *) oid_string,
9409                                                   strlen(oid_string) + 1);
9410                 }
9411
9412                 result = winreg_printer_update_changeid(p->mem_ctx, b,
9413                                                         lp_const_servicename(snum));
9414
9415         }
9416
9417 done:
9418         talloc_free(pinfo2);
9419         return result;
9420 }
9421
9422 /****************************************************************
9423  _spoolss_DeletePrinterDataEx
9424 ****************************************************************/
9425
9426 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9427                                     struct spoolss_DeletePrinterDataEx *r)
9428 {
9429         const char *printer;
9430         int             snum=0;
9431         WERROR          status = WERR_OK;
9432         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9433
9434         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9435
9436         if (!Printer) {
9437                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9438                         "Invalid handle (%s:%u:%u).\n",
9439                         OUR_HANDLE(r->in.handle)));
9440                 return WERR_BADFID;
9441         }
9442
9443         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9444                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9445                         "printer properties change denied by handle\n"));
9446                 return WERR_ACCESS_DENIED;
9447         }
9448
9449         if (!r->in.value_name || !r->in.key_name) {
9450                 return WERR_NOMEM;
9451         }
9452
9453         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9454                 return WERR_BADFID;
9455         }
9456         printer = lp_const_servicename(snum);
9457
9458         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9459                                               get_session_info_system(),
9460                                               p->msg_ctx,
9461                                               printer,
9462                                               r->in.key_name,
9463                                               r->in.value_name);
9464         if (W_ERROR_IS_OK(status)) {
9465                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9466                                                         get_session_info_system(),
9467                                                         p->msg_ctx,
9468                                                         printer);
9469         }
9470
9471         return status;
9472 }
9473
9474 /****************************************************************
9475  _spoolss_EnumPrinterKey
9476 ****************************************************************/
9477
9478 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9479                                struct spoolss_EnumPrinterKey *r)
9480 {
9481         uint32_t        num_keys;
9482         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9483         int             snum = 0;
9484         WERROR          result = WERR_BADFILE;
9485         const char **array = NULL;
9486         DATA_BLOB blob;
9487
9488         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9489
9490         if (!Printer) {
9491                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9492                         OUR_HANDLE(r->in.handle)));
9493                 return WERR_BADFID;
9494         }
9495
9496         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9497                 return WERR_BADFID;
9498         }
9499
9500         result = winreg_enum_printer_key_internal(p->mem_ctx,
9501                                          get_session_info_system(),
9502                                          p->msg_ctx,
9503                                          lp_const_servicename(snum),
9504                                          r->in.key_name,
9505                                          &num_keys,
9506                                          &array);
9507         if (!W_ERROR_IS_OK(result)) {
9508                 goto done;
9509         }
9510
9511         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9512                 result = WERR_NOMEM;
9513                 goto done;
9514         }
9515
9516         *r->out._ndr_size = r->in.offered / 2;
9517         *r->out.needed = blob.length;
9518
9519         if (r->in.offered < *r->out.needed) {
9520                 result = WERR_MORE_DATA;
9521         } else {
9522                 result = WERR_OK;
9523                 r->out.key_buffer->string_array = array;
9524         }
9525
9526  done:
9527         if (!W_ERROR_IS_OK(result)) {
9528                 TALLOC_FREE(array);
9529                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9530                         *r->out.needed = 0;
9531                 }
9532         }
9533
9534         return result;
9535 }
9536
9537 /****************************************************************
9538  _spoolss_DeletePrinterKey
9539 ****************************************************************/
9540
9541 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9542                                  struct spoolss_DeletePrinterKey *r)
9543 {
9544         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9545         int                     snum=0;
9546         WERROR                  status;
9547         const char *printer;
9548         struct dcerpc_binding_handle *b;
9549
9550         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9551
9552         if (!Printer) {
9553                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9554                         OUR_HANDLE(r->in.handle)));
9555                 return WERR_BADFID;
9556         }
9557
9558         /* if keyname == NULL, return error */
9559         if ( !r->in.key_name )
9560                 return WERR_INVALID_PARAM;
9561
9562         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9563                 return WERR_BADFID;
9564         }
9565
9566         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9567                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9568                         "printer properties change denied by handle\n"));
9569                 return WERR_ACCESS_DENIED;
9570         }
9571
9572         printer = lp_const_servicename(snum);
9573
9574         status = winreg_printer_binding_handle(p->mem_ctx,
9575                                                get_session_info_system(),
9576                                                p->msg_ctx,
9577                                                &b);
9578         if (!W_ERROR_IS_OK(status)) {
9579                 return status;
9580         }
9581
9582         /* delete the key and all subkeys */
9583         status = winreg_delete_printer_key(p->mem_ctx, b,
9584                                            printer,
9585                                            r->in.key_name);
9586         if (W_ERROR_IS_OK(status)) {
9587                 status = winreg_printer_update_changeid(p->mem_ctx, b,
9588                                                         printer);
9589         }
9590
9591         return status;
9592 }
9593
9594 /****************************************************************
9595  _spoolss_EnumPrinterDataEx
9596 ****************************************************************/
9597
9598 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9599                                   struct spoolss_EnumPrinterDataEx *r)
9600 {
9601         uint32_t        count = 0;
9602         struct spoolss_PrinterEnumValues *info = NULL;
9603         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9604         int             snum;
9605         WERROR          result;
9606
9607         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9608
9609         *r->out.count = 0;
9610         *r->out.needed = 0;
9611         *r->out.info = NULL;
9612
9613         if (!Printer) {
9614                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9615                         OUR_HANDLE(r->in.handle)));
9616                 return WERR_BADFID;
9617         }
9618
9619         /*
9620          * first check for a keyname of NULL or "".  Win2k seems to send
9621          * this a lot and we should send back WERR_INVALID_PARAM
9622          * no need to spend time looking up the printer in this case.
9623          * --jerry
9624          */
9625
9626         if (!strlen(r->in.key_name)) {
9627                 result = WERR_INVALID_PARAM;
9628                 goto done;
9629         }
9630
9631         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9632                 return WERR_BADFID;
9633         }
9634
9635         /* now look for a match on the key name */
9636         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9637                                             get_session_info_system(),
9638                                             p->msg_ctx,
9639                                             lp_const_servicename(snum),
9640                                             r->in.key_name,
9641                                             &count,
9642                                             &info);
9643         if (!W_ERROR_IS_OK(result)) {
9644                 goto done;
9645         }
9646
9647 #if 0 /* FIXME - gd */
9648         /* housekeeping information in the reply */
9649
9650         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9651          * the hand marshalled container size is a multiple
9652          * of 4 bytes for RPC alignment.
9653          */
9654
9655         if (needed % 4) {
9656                 needed += 4-(needed % 4);
9657         }
9658 #endif
9659         *r->out.count   = count;
9660         *r->out.info    = info;
9661
9662  done:
9663         if (!W_ERROR_IS_OK(result)) {
9664                 return result;
9665         }
9666
9667         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9668                                                spoolss_EnumPrinterDataEx,
9669                                                *r->out.info,
9670                                                *r->out.count);
9671         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9672         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9673
9674         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9675 }
9676
9677 /****************************************************************************
9678 ****************************************************************************/
9679
9680 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9681                                                  const char *servername,
9682                                                  const char *environment,
9683                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9684 {
9685         WERROR werr;
9686         char *path = NULL;
9687
9688         werr = compose_spoolss_server_path(mem_ctx,
9689                                            servername,
9690                                            environment,
9691                                            SPOOLSS_PRTPROCS_PATH,
9692                                            &path);
9693         if (!W_ERROR_IS_OK(werr)) {
9694                 return werr;
9695         }
9696
9697         DEBUG(4,("print processor directory: [%s]\n", path));
9698
9699         r->directory_name = path;
9700
9701         return WERR_OK;
9702 }
9703
9704 /****************************************************************
9705  _spoolss_GetPrintProcessorDirectory
9706 ****************************************************************/
9707
9708 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9709                                            struct spoolss_GetPrintProcessorDirectory *r)
9710 {
9711         WERROR result;
9712         char *prnproc_share = NULL;
9713         bool prnproc_share_exists = false;
9714         int snum;
9715
9716         /* that's an [in out] buffer */
9717
9718         if (!r->in.buffer && (r->in.offered != 0)) {
9719                 return WERR_INVALID_PARAM;
9720         }
9721
9722         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9723                 r->in.level));
9724
9725         *r->out.needed = 0;
9726
9727         /* r->in.level is ignored */
9728
9729         /* We always should reply with a local print processor directory so that
9730          * users are not forced to have a [prnproc$] share on the Samba spoolss
9731          * server, if users decide to do so, lets announce it though - Guenther */
9732
9733         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9734         if (!prnproc_share) {
9735                 return WERR_NOMEM;
9736         }
9737         if (snum != -1) {
9738                 prnproc_share_exists = true;
9739         }
9740
9741         result = getprintprocessordirectory_level_1(p->mem_ctx,
9742                                                     prnproc_share_exists ? r->in.server : NULL,
9743                                                     r->in.environment,
9744                                                     &r->out.info->info1);
9745         if (!W_ERROR_IS_OK(result)) {
9746                 TALLOC_FREE(r->out.info);
9747                 return result;
9748         }
9749
9750         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9751                                                                                    r->out.info, r->in.level);
9752         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9753
9754         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9755 }
9756
9757 /*******************************************************************
9758  ********************************************************************/
9759
9760 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9761                                const char *dllname)
9762 {
9763         enum ndr_err_code ndr_err;
9764         struct spoolss_MonitorUi ui;
9765
9766         ui.dll_name = dllname;
9767
9768         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9769                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9770         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9771                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9772         }
9773         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9774 }
9775
9776 /*******************************************************************
9777  Streams the monitor UI DLL name in UNICODE
9778 *******************************************************************/
9779
9780 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9781                                struct security_token *token, DATA_BLOB *in,
9782                                DATA_BLOB *out, uint32_t *needed)
9783 {
9784         const char *dllname = "tcpmonui.dll";
9785
9786         *needed = (strlen(dllname)+1) * 2;
9787
9788         if (out->length < *needed) {
9789                 return WERR_INSUFFICIENT_BUFFER;
9790         }
9791
9792         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9793                 return WERR_NOMEM;
9794         }
9795
9796         return WERR_OK;
9797 }
9798
9799 /*******************************************************************
9800  ********************************************************************/
9801
9802 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9803                              struct spoolss_PortData1 *port1,
9804                              const DATA_BLOB *buf)
9805 {
9806         enum ndr_err_code ndr_err;
9807         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9808                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9809         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9810                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9811         }
9812         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9813 }
9814
9815 /*******************************************************************
9816  ********************************************************************/
9817
9818 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9819                              struct spoolss_PortData2 *port2,
9820                              const DATA_BLOB *buf)
9821 {
9822         enum ndr_err_code ndr_err;
9823         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9824                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9825         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9826                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9827         }
9828         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9829 }
9830
9831 /*******************************************************************
9832  Create a new TCP/IP port
9833 *******************************************************************/
9834
9835 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9836                              struct security_token *token, DATA_BLOB *in,
9837                              DATA_BLOB *out, uint32_t *needed)
9838 {
9839         struct spoolss_PortData1 port1;
9840         struct spoolss_PortData2 port2;
9841         char *device_uri = NULL;
9842         uint32_t version;
9843
9844         const char *portname;
9845         const char *hostaddress;
9846         const char *queue;
9847         uint32_t port_number;
9848         uint32_t protocol;
9849
9850         /* peek for spoolss_PortData version */
9851
9852         if (!in || (in->length < (128 + 4))) {
9853                 return WERR_GENERAL_FAILURE;
9854         }
9855
9856         version = IVAL(in->data, 128);
9857
9858         switch (version) {
9859                 case 1:
9860                         ZERO_STRUCT(port1);
9861
9862                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9863                                 return WERR_NOMEM;
9864                         }
9865
9866                         portname        = port1.portname;
9867                         hostaddress     = port1.hostaddress;
9868                         queue           = port1.queue;
9869                         protocol        = port1.protocol;
9870                         port_number     = port1.port_number;
9871
9872                         break;
9873                 case 2:
9874                         ZERO_STRUCT(port2);
9875
9876                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9877                                 return WERR_NOMEM;
9878                         }
9879
9880                         portname        = port2.portname;
9881                         hostaddress     = port2.hostaddress;
9882                         queue           = port2.queue;
9883                         protocol        = port2.protocol;
9884                         port_number     = port2.port_number;
9885
9886                         break;
9887                 default:
9888                         DEBUG(1,("xcvtcp_addport: "
9889                                 "unknown version of port_data: %d\n", version));
9890                         return WERR_UNKNOWN_PORT;
9891         }
9892
9893         /* create the device URI and call the add_port_hook() */
9894
9895         switch (protocol) {
9896         case PROTOCOL_RAWTCP_TYPE:
9897                 device_uri = talloc_asprintf(mem_ctx,
9898                                 "socket://%s:%d/", hostaddress,
9899                                 port_number);
9900                 break;
9901
9902         case PROTOCOL_LPR_TYPE:
9903                 device_uri = talloc_asprintf(mem_ctx,
9904                         "lpr://%s/%s", hostaddress, queue );
9905                 break;
9906
9907         default:
9908                 return WERR_UNKNOWN_PORT;
9909         }
9910
9911         if (!device_uri) {
9912                 return WERR_NOMEM;
9913         }
9914
9915         return add_port_hook(mem_ctx, token, portname, device_uri);
9916 }
9917
9918 /*******************************************************************
9919 *******************************************************************/
9920
9921 struct xcv_api_table xcvtcp_cmds[] = {
9922         { "MonitorUI",  xcvtcp_monitorui },
9923         { "AddPort",    xcvtcp_addport},
9924         { NULL,         NULL }
9925 };
9926
9927 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9928                                      struct security_token *token, const char *command,
9929                                      DATA_BLOB *inbuf,
9930                                      DATA_BLOB *outbuf,
9931                                      uint32_t *needed )
9932 {
9933         int i;
9934
9935         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9936
9937         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9938                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9939                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9940         }
9941
9942         return WERR_BADFUNC;
9943 }
9944
9945 /*******************************************************************
9946 *******************************************************************/
9947 #if 0   /* don't support management using the "Local Port" monitor */
9948
9949 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9950                                  struct security_token *token, DATA_BLOB *in,
9951                                  DATA_BLOB *out, uint32_t *needed)
9952 {
9953         const char *dllname = "localui.dll";
9954
9955         *needed = (strlen(dllname)+1) * 2;
9956
9957         if (out->length < *needed) {
9958                 return WERR_INSUFFICIENT_BUFFER;
9959         }
9960
9961         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9962                 return WERR_NOMEM;
9963         }
9964
9965         return WERR_OK;
9966 }
9967
9968 /*******************************************************************
9969 *******************************************************************/
9970
9971 struct xcv_api_table xcvlocal_cmds[] = {
9972         { "MonitorUI",  xcvlocal_monitorui },
9973         { NULL,         NULL }
9974 };
9975 #else
9976 struct xcv_api_table xcvlocal_cmds[] = {
9977         { NULL,         NULL }
9978 };
9979 #endif
9980
9981
9982
9983 /*******************************************************************
9984 *******************************************************************/
9985
9986 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9987                                        struct security_token *token, const char *command,
9988                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9989                                        uint32_t *needed)
9990 {
9991         int i;
9992
9993         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9994
9995         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9996                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9997                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9998         }
9999         return WERR_BADFUNC;
10000 }
10001
10002 /****************************************************************
10003  _spoolss_XcvData
10004 ****************************************************************/
10005
10006 WERROR _spoolss_XcvData(struct pipes_struct *p,
10007                         struct spoolss_XcvData *r)
10008 {
10009         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10010         DATA_BLOB out_data = data_blob_null;
10011         WERROR werror;
10012
10013         if (!Printer) {
10014                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10015                         OUR_HANDLE(r->in.handle)));
10016                 return WERR_BADFID;
10017         }
10018
10019         /* Has to be a handle to the TCP/IP port monitor */
10020
10021         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10022                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10023                 return WERR_BADFID;
10024         }
10025
10026         /* requires administrative access to the server */
10027
10028         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10029                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10030                 return WERR_ACCESS_DENIED;
10031         }
10032
10033         /* Allocate the outgoing buffer */
10034
10035         if (r->in.out_data_size) {
10036                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10037                 if (out_data.data == NULL) {
10038                         return WERR_NOMEM;
10039                 }
10040         }
10041
10042         switch ( Printer->printer_type ) {
10043         case SPLHND_PORTMON_TCP:
10044                 werror = process_xcvtcp_command(p->mem_ctx,
10045                                                 p->session_info->security_token,
10046                                                 r->in.function_name,
10047                                                 &r->in.in_data, &out_data,
10048                                                 r->out.needed);
10049                 break;
10050         case SPLHND_PORTMON_LOCAL:
10051                 werror = process_xcvlocal_command(p->mem_ctx,
10052                                                   p->session_info->security_token,
10053                                                   r->in.function_name,
10054                                                   &r->in.in_data, &out_data,
10055                                                   r->out.needed);
10056                 break;
10057         default:
10058                 werror = WERR_INVALID_PRINT_MONITOR;
10059         }
10060
10061         if (!W_ERROR_IS_OK(werror)) {
10062                 return werror;
10063         }
10064
10065         *r->out.status_code = 0;
10066
10067         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10068                 memcpy(r->out.out_data, out_data.data,
10069                         MIN(r->in.out_data_size, out_data.length));
10070         }
10071
10072         return WERR_OK;
10073 }
10074
10075 /****************************************************************
10076  _spoolss_AddPrintProcessor
10077 ****************************************************************/
10078
10079 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10080                                   struct spoolss_AddPrintProcessor *r)
10081 {
10082         /* for now, just indicate success and ignore the add.  We'll
10083            automatically set the winprint processor for printer
10084            entries later.  Used to debug the LexMark Optra S 1855 PCL
10085            driver --jerry */
10086
10087         return WERR_OK;
10088 }
10089
10090 /****************************************************************
10091  _spoolss_AddPort
10092 ****************************************************************/
10093
10094 WERROR _spoolss_AddPort(struct pipes_struct *p,
10095                         struct spoolss_AddPort *r)
10096 {
10097         /* do what w2k3 does */
10098
10099         return WERR_NOT_SUPPORTED;
10100 }
10101
10102 /****************************************************************
10103  _spoolss_GetPrinterDriver
10104 ****************************************************************/
10105
10106 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10107                                  struct spoolss_GetPrinterDriver *r)
10108 {
10109         p->rng_fault_state = true;
10110         return WERR_NOT_SUPPORTED;
10111 }
10112
10113 /****************************************************************
10114  _spoolss_ReadPrinter
10115 ****************************************************************/
10116
10117 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10118                             struct spoolss_ReadPrinter *r)
10119 {
10120         p->rng_fault_state = true;
10121         return WERR_NOT_SUPPORTED;
10122 }
10123
10124 /****************************************************************
10125  _spoolss_WaitForPrinterChange
10126 ****************************************************************/
10127
10128 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10129                                      struct spoolss_WaitForPrinterChange *r)
10130 {
10131         p->rng_fault_state = true;
10132         return WERR_NOT_SUPPORTED;
10133 }
10134
10135 /****************************************************************
10136  _spoolss_ConfigurePort
10137 ****************************************************************/
10138
10139 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10140                               struct spoolss_ConfigurePort *r)
10141 {
10142         p->rng_fault_state = true;
10143         return WERR_NOT_SUPPORTED;
10144 }
10145
10146 /****************************************************************
10147  _spoolss_DeletePort
10148 ****************************************************************/
10149
10150 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10151                            struct spoolss_DeletePort *r)
10152 {
10153         p->rng_fault_state = true;
10154         return WERR_NOT_SUPPORTED;
10155 }
10156
10157 /****************************************************************
10158  _spoolss_CreatePrinterIC
10159 ****************************************************************/
10160
10161 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10162                                 struct spoolss_CreatePrinterIC *r)
10163 {
10164         p->rng_fault_state = true;
10165         return WERR_NOT_SUPPORTED;
10166 }
10167
10168 /****************************************************************
10169  _spoolss_PlayGDIScriptOnPrinterIC
10170 ****************************************************************/
10171
10172 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10173                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10174 {
10175         p->rng_fault_state = true;
10176         return WERR_NOT_SUPPORTED;
10177 }
10178
10179 /****************************************************************
10180  _spoolss_DeletePrinterIC
10181 ****************************************************************/
10182
10183 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10184                                 struct spoolss_DeletePrinterIC *r)
10185 {
10186         p->rng_fault_state = true;
10187         return WERR_NOT_SUPPORTED;
10188 }
10189
10190 /****************************************************************
10191  _spoolss_AddPrinterConnection
10192 ****************************************************************/
10193
10194 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10195                                      struct spoolss_AddPrinterConnection *r)
10196 {
10197         p->rng_fault_state = true;
10198         return WERR_NOT_SUPPORTED;
10199 }
10200
10201 /****************************************************************
10202  _spoolss_DeletePrinterConnection
10203 ****************************************************************/
10204
10205 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10206                                         struct spoolss_DeletePrinterConnection *r)
10207 {
10208         p->rng_fault_state = true;
10209         return WERR_NOT_SUPPORTED;
10210 }
10211
10212 /****************************************************************
10213  _spoolss_PrinterMessageBox
10214 ****************************************************************/
10215
10216 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10217                                   struct spoolss_PrinterMessageBox *r)
10218 {
10219         p->rng_fault_state = true;
10220         return WERR_NOT_SUPPORTED;
10221 }
10222
10223 /****************************************************************
10224  _spoolss_AddMonitor
10225 ****************************************************************/
10226
10227 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10228                            struct spoolss_AddMonitor *r)
10229 {
10230         p->rng_fault_state = true;
10231         return WERR_NOT_SUPPORTED;
10232 }
10233
10234 /****************************************************************
10235  _spoolss_DeleteMonitor
10236 ****************************************************************/
10237
10238 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10239                               struct spoolss_DeleteMonitor *r)
10240 {
10241         p->rng_fault_state = true;
10242         return WERR_NOT_SUPPORTED;
10243 }
10244
10245 /****************************************************************
10246  _spoolss_DeletePrintProcessor
10247 ****************************************************************/
10248
10249 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10250                                      struct spoolss_DeletePrintProcessor *r)
10251 {
10252         p->rng_fault_state = true;
10253         return WERR_NOT_SUPPORTED;
10254 }
10255
10256 /****************************************************************
10257  _spoolss_AddPrintProvidor
10258 ****************************************************************/
10259
10260 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10261                                  struct spoolss_AddPrintProvidor *r)
10262 {
10263         p->rng_fault_state = true;
10264         return WERR_NOT_SUPPORTED;
10265 }
10266
10267 /****************************************************************
10268  _spoolss_DeletePrintProvidor
10269 ****************************************************************/
10270
10271 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10272                                     struct spoolss_DeletePrintProvidor *r)
10273 {
10274         p->rng_fault_state = true;
10275         return WERR_NOT_SUPPORTED;
10276 }
10277
10278 /****************************************************************
10279  _spoolss_FindFirstPrinterChangeNotification
10280 ****************************************************************/
10281
10282 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10283                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10284 {
10285         p->rng_fault_state = true;
10286         return WERR_NOT_SUPPORTED;
10287 }
10288
10289 /****************************************************************
10290  _spoolss_FindNextPrinterChangeNotification
10291 ****************************************************************/
10292
10293 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10294                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10295 {
10296         p->rng_fault_state = true;
10297         return WERR_NOT_SUPPORTED;
10298 }
10299
10300 /****************************************************************
10301  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10302 ****************************************************************/
10303
10304 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10305                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10306 {
10307         p->rng_fault_state = true;
10308         return WERR_NOT_SUPPORTED;
10309 }
10310
10311 /****************************************************************
10312  _spoolss_ReplyOpenPrinter
10313 ****************************************************************/
10314
10315 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10316                                  struct spoolss_ReplyOpenPrinter *r)
10317 {
10318         p->rng_fault_state = true;
10319         return WERR_NOT_SUPPORTED;
10320 }
10321
10322 /****************************************************************
10323  _spoolss_RouterReplyPrinter
10324 ****************************************************************/
10325
10326 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10327                                    struct spoolss_RouterReplyPrinter *r)
10328 {
10329         p->rng_fault_state = true;
10330         return WERR_NOT_SUPPORTED;
10331 }
10332
10333 /****************************************************************
10334  _spoolss_ReplyClosePrinter
10335 ****************************************************************/
10336
10337 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10338                                   struct spoolss_ReplyClosePrinter *r)
10339 {
10340         p->rng_fault_state = true;
10341         return WERR_NOT_SUPPORTED;
10342 }
10343
10344 /****************************************************************
10345  _spoolss_AddPortEx
10346 ****************************************************************/
10347
10348 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10349                           struct spoolss_AddPortEx *r)
10350 {
10351         p->rng_fault_state = true;
10352         return WERR_NOT_SUPPORTED;
10353 }
10354
10355 /****************************************************************
10356  _spoolss_RouterFindFirstPrinterChangeNotification
10357 ****************************************************************/
10358
10359 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10360                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10361 {
10362         p->rng_fault_state = true;
10363         return WERR_NOT_SUPPORTED;
10364 }
10365
10366 /****************************************************************
10367  _spoolss_SpoolerInit
10368 ****************************************************************/
10369
10370 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10371                             struct spoolss_SpoolerInit *r)
10372 {
10373         p->rng_fault_state = true;
10374         return WERR_NOT_SUPPORTED;
10375 }
10376
10377 /****************************************************************
10378  _spoolss_ResetPrinterEx
10379 ****************************************************************/
10380
10381 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10382                                struct spoolss_ResetPrinterEx *r)
10383 {
10384         p->rng_fault_state = true;
10385         return WERR_NOT_SUPPORTED;
10386 }
10387
10388 /****************************************************************
10389  _spoolss_RouterReplyPrinterEx
10390 ****************************************************************/
10391
10392 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10393                                      struct spoolss_RouterReplyPrinterEx *r)
10394 {
10395         p->rng_fault_state = true;
10396         return WERR_NOT_SUPPORTED;
10397 }
10398
10399 /****************************************************************
10400  _spoolss_44
10401 ****************************************************************/
10402
10403 WERROR _spoolss_44(struct pipes_struct *p,
10404                    struct spoolss_44 *r)
10405 {
10406         p->rng_fault_state = true;
10407         return WERR_NOT_SUPPORTED;
10408 }
10409
10410 /****************************************************************
10411  _spoolss_SetPort
10412 ****************************************************************/
10413
10414 WERROR _spoolss_SetPort(struct pipes_struct *p,
10415                         struct spoolss_SetPort *r)
10416 {
10417         p->rng_fault_state = true;
10418         return WERR_NOT_SUPPORTED;
10419 }
10420
10421 /****************************************************************
10422  _spoolss_4a
10423 ****************************************************************/
10424
10425 WERROR _spoolss_4a(struct pipes_struct *p,
10426                    struct spoolss_4a *r)
10427 {
10428         p->rng_fault_state = true;
10429         return WERR_NOT_SUPPORTED;
10430 }
10431
10432 /****************************************************************
10433  _spoolss_4b
10434 ****************************************************************/
10435
10436 WERROR _spoolss_4b(struct pipes_struct *p,
10437                    struct spoolss_4b *r)
10438 {
10439         p->rng_fault_state = true;
10440         return WERR_NOT_SUPPORTED;
10441 }
10442
10443 /****************************************************************
10444  _spoolss_4c
10445 ****************************************************************/
10446
10447 WERROR _spoolss_4c(struct pipes_struct *p,
10448                    struct spoolss_4c *r)
10449 {
10450         p->rng_fault_state = true;
10451         return WERR_NOT_SUPPORTED;
10452 }
10453
10454 /****************************************************************
10455  _spoolss_53
10456 ****************************************************************/
10457
10458 WERROR _spoolss_53(struct pipes_struct *p,
10459                    struct spoolss_53 *r)
10460 {
10461         p->rng_fault_state = true;
10462         return WERR_NOT_SUPPORTED;
10463 }
10464
10465 /****************************************************************
10466  _spoolss_AddPerMachineConnection
10467 ****************************************************************/
10468
10469 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10470                                         struct spoolss_AddPerMachineConnection *r)
10471 {
10472         p->rng_fault_state = true;
10473         return WERR_NOT_SUPPORTED;
10474 }
10475
10476 /****************************************************************
10477  _spoolss_DeletePerMachineConnection
10478 ****************************************************************/
10479
10480 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10481                                            struct spoolss_DeletePerMachineConnection *r)
10482 {
10483         p->rng_fault_state = true;
10484         return WERR_NOT_SUPPORTED;
10485 }
10486
10487 /****************************************************************
10488  _spoolss_EnumPerMachineConnections
10489 ****************************************************************/
10490
10491 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10492                                           struct spoolss_EnumPerMachineConnections *r)
10493 {
10494         p->rng_fault_state = true;
10495         return WERR_NOT_SUPPORTED;
10496 }
10497
10498 /****************************************************************
10499  _spoolss_5a
10500 ****************************************************************/
10501
10502 WERROR _spoolss_5a(struct pipes_struct *p,
10503                    struct spoolss_5a *r)
10504 {
10505         p->rng_fault_state = true;
10506         return WERR_NOT_SUPPORTED;
10507 }
10508
10509 /****************************************************************
10510  _spoolss_5b
10511 ****************************************************************/
10512
10513 WERROR _spoolss_5b(struct pipes_struct *p,
10514                    struct spoolss_5b *r)
10515 {
10516         p->rng_fault_state = true;
10517         return WERR_NOT_SUPPORTED;
10518 }
10519
10520 /****************************************************************
10521  _spoolss_5c
10522 ****************************************************************/
10523
10524 WERROR _spoolss_5c(struct pipes_struct *p,
10525                    struct spoolss_5c *r)
10526 {
10527         p->rng_fault_state = true;
10528         return WERR_NOT_SUPPORTED;
10529 }
10530
10531 /****************************************************************
10532  _spoolss_5d
10533 ****************************************************************/
10534
10535 WERROR _spoolss_5d(struct pipes_struct *p,
10536                    struct spoolss_5d *r)
10537 {
10538         p->rng_fault_state = true;
10539         return WERR_NOT_SUPPORTED;
10540 }
10541
10542 /****************************************************************
10543  _spoolss_5e
10544 ****************************************************************/
10545
10546 WERROR _spoolss_5e(struct pipes_struct *p,
10547                    struct spoolss_5e *r)
10548 {
10549         p->rng_fault_state = true;
10550         return WERR_NOT_SUPPORTED;
10551 }
10552
10553 /****************************************************************
10554  _spoolss_5f
10555 ****************************************************************/
10556
10557 WERROR _spoolss_5f(struct pipes_struct *p,
10558                    struct spoolss_5f *r)
10559 {
10560         p->rng_fault_state = true;
10561         return WERR_NOT_SUPPORTED;
10562 }
10563
10564 /****************************************************************
10565  _spoolss_60
10566 ****************************************************************/
10567
10568 WERROR _spoolss_60(struct pipes_struct *p,
10569                    struct spoolss_60 *r)
10570 {
10571         p->rng_fault_state = true;
10572         return WERR_NOT_SUPPORTED;
10573 }
10574
10575 /****************************************************************
10576  _spoolss_61
10577 ****************************************************************/
10578
10579 WERROR _spoolss_61(struct pipes_struct *p,
10580                    struct spoolss_61 *r)
10581 {
10582         p->rng_fault_state = true;
10583         return WERR_NOT_SUPPORTED;
10584 }
10585
10586 /****************************************************************
10587  _spoolss_62
10588 ****************************************************************/
10589
10590 WERROR _spoolss_62(struct pipes_struct *p,
10591                    struct spoolss_62 *r)
10592 {
10593         p->rng_fault_state = true;
10594         return WERR_NOT_SUPPORTED;
10595 }
10596
10597 /****************************************************************
10598  _spoolss_63
10599 ****************************************************************/
10600
10601 WERROR _spoolss_63(struct pipes_struct *p,
10602                    struct spoolss_63 *r)
10603 {
10604         p->rng_fault_state = true;
10605         return WERR_NOT_SUPPORTED;
10606 }
10607
10608 /****************************************************************
10609  _spoolss_64
10610 ****************************************************************/
10611
10612 WERROR _spoolss_64(struct pipes_struct *p,
10613                    struct spoolss_64 *r)
10614 {
10615         p->rng_fault_state = true;
10616         return WERR_NOT_SUPPORTED;
10617 }
10618
10619 /****************************************************************
10620  _spoolss_65
10621 ****************************************************************/
10622
10623 WERROR _spoolss_65(struct pipes_struct *p,
10624                    struct spoolss_65 *r)
10625 {
10626         p->rng_fault_state = true;
10627         return WERR_NOT_SUPPORTED;
10628 }
10629
10630 /****************************************************************
10631  _spoolss_GetCorePrinterDrivers
10632 ****************************************************************/
10633
10634 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10635                                       struct spoolss_GetCorePrinterDrivers *r)
10636 {
10637         p->rng_fault_state = true;
10638         return WERR_NOT_SUPPORTED;
10639 }
10640
10641 /****************************************************************
10642  _spoolss_67
10643 ****************************************************************/
10644
10645 WERROR _spoolss_67(struct pipes_struct *p,
10646                    struct spoolss_67 *r)
10647 {
10648         p->rng_fault_state = true;
10649         return WERR_NOT_SUPPORTED;
10650 }
10651
10652 /****************************************************************
10653  _spoolss_GetPrinterDriverPackagePath
10654 ****************************************************************/
10655
10656 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10657                                             struct spoolss_GetPrinterDriverPackagePath *r)
10658 {
10659         p->rng_fault_state = true;
10660         return WERR_NOT_SUPPORTED;
10661 }
10662
10663 /****************************************************************
10664  _spoolss_69
10665 ****************************************************************/
10666
10667 WERROR _spoolss_69(struct pipes_struct *p,
10668                    struct spoolss_69 *r)
10669 {
10670         p->rng_fault_state = true;
10671         return WERR_NOT_SUPPORTED;
10672 }
10673
10674 /****************************************************************
10675  _spoolss_6a
10676 ****************************************************************/
10677
10678 WERROR _spoolss_6a(struct pipes_struct *p,
10679                    struct spoolss_6a *r)
10680 {
10681         p->rng_fault_state = true;
10682         return WERR_NOT_SUPPORTED;
10683 }
10684
10685 /****************************************************************
10686  _spoolss_6b
10687 ****************************************************************/
10688
10689 WERROR _spoolss_6b(struct pipes_struct *p,
10690                    struct spoolss_6b *r)
10691 {
10692         p->rng_fault_state = true;
10693         return WERR_NOT_SUPPORTED;
10694 }
10695
10696 /****************************************************************
10697  _spoolss_6c
10698 ****************************************************************/
10699
10700 WERROR _spoolss_6c(struct pipes_struct *p,
10701                    struct spoolss_6c *r)
10702 {
10703         p->rng_fault_state = true;
10704         return WERR_NOT_SUPPORTED;
10705 }
10706
10707 /****************************************************************
10708  _spoolss_6d
10709 ****************************************************************/
10710
10711 WERROR _spoolss_6d(struct pipes_struct *p,
10712                    struct spoolss_6d *r)
10713 {
10714         p->rng_fault_state = true;
10715         return WERR_NOT_SUPPORTED;
10716 }