s3-spoolss: Removed wrong comment.
[samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry.h"
39 #include "registry/reg_objects.h"
40
41 /* macros stolen from s4 spoolss server */
42 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
43         ((info)?ndr_size_##fn(info, level, 0):0)
44
45 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
46         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
47
48 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
49         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
50
51 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
52
53
54 extern userdom_struct current_user_info;
55
56 #undef DBGC_CLASS
57 #define DBGC_CLASS DBGC_RPC_SRV
58
59 #ifndef MAX_OPEN_PRINTER_EXS
60 #define MAX_OPEN_PRINTER_EXS 50
61 #endif
62
63 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
64
65 static Printer_entry *printers_list;
66
67 typedef struct _counter_printer_0 {
68         struct _counter_printer_0 *next;
69         struct _counter_printer_0 *prev;
70
71         int snum;
72         uint32_t counter;
73 } counter_printer_0;
74
75 static counter_printer_0 *counter_list;
76
77 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
78 static uint32_t smb_connections = 0;
79
80
81 /* in printing/nt_printing.c */
82
83 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
84
85 /* API table for Xcv Monitor functions */
86
87 struct xcv_api_table {
88         const char *name;
89         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
90 };
91
92 /********************************************************************
93  * Canonicalize servername.
94  ********************************************************************/
95
96 static const char *canon_servername(const char *servername)
97 {
98         const char *pservername = servername;
99         while (*pservername == '\\') {
100                 pservername++;
101         }
102         return pservername;
103 }
104
105 /* translate between internal status numbers and NT status numbers */
106 static int nt_printj_status(int v)
107 {
108         switch (v) {
109         case LPQ_QUEUED:
110                 return 0;
111         case LPQ_PAUSED:
112                 return JOB_STATUS_PAUSED;
113         case LPQ_SPOOLING:
114                 return JOB_STATUS_SPOOLING;
115         case LPQ_PRINTING:
116                 return JOB_STATUS_PRINTING;
117         case LPQ_ERROR:
118                 return JOB_STATUS_ERROR;
119         case LPQ_DELETING:
120                 return JOB_STATUS_DELETING;
121         case LPQ_OFFLINE:
122                 return JOB_STATUS_OFFLINE;
123         case LPQ_PAPEROUT:
124                 return JOB_STATUS_PAPEROUT;
125         case LPQ_PRINTED:
126                 return JOB_STATUS_PRINTED;
127         case LPQ_DELETED:
128                 return JOB_STATUS_DELETED;
129         case LPQ_BLOCKED:
130                 return JOB_STATUS_BLOCKED_DEVQ;
131         case LPQ_USER_INTERVENTION:
132                 return JOB_STATUS_USER_INTERVENTION;
133         }
134         return 0;
135 }
136
137 static int nt_printq_status(int v)
138 {
139         switch (v) {
140         case LPQ_PAUSED:
141                 return PRINTER_STATUS_PAUSED;
142         case LPQ_QUEUED:
143         case LPQ_SPOOLING:
144         case LPQ_PRINTING:
145                 return 0;
146         }
147         return 0;
148 }
149
150 /***************************************************************************
151  Disconnect from the client
152 ****************************************************************************/
153
154 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
155 {
156         WERROR result;
157         NTSTATUS status;
158
159         /*
160          * Tell the specific printing tdb we no longer want messages for this printer
161          * by deregistering our PID.
162          */
163
164         if (!print_notify_deregister_pid(snum))
165                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
166
167         /* weird if the test succeds !!! */
168         if (smb_connections==0) {
169                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
170                 return;
171         }
172
173         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
174                                                   handle,
175                                                   &result);
176         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
177                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
178                         win_errstr(result)));
179
180         /* if it's the last connection, deconnect the IPC$ share */
181         if (smb_connections==1) {
182
183                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
184                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
185
186                 messaging_deregister(smbd_messaging_context(),
187                                      MSG_PRINTER_NOTIFY2, NULL);
188
189                 /* Tell the connections db we're no longer interested in
190                  * printer notify messages. */
191
192                 serverid_register_msg_flags(
193                         messaging_server_id(smbd_messaging_context()),
194                         false, FLAG_MSG_PRINT_NOTIFY);
195         }
196
197         smb_connections--;
198 }
199
200 /****************************************************************************
201  Functions to free a printer entry datastruct.
202 ****************************************************************************/
203
204 static int printer_entry_destructor(Printer_entry *Printer)
205 {
206         if (Printer->notify.client_connected == true) {
207                 int snum = -1;
208
209                 if ( Printer->printer_type == SPLHND_SERVER) {
210                         snum = -1;
211                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
212                 } else if (Printer->printer_type == SPLHND_PRINTER) {
213                         snum = print_queue_snum(Printer->sharename);
214                         if (snum != -1)
215                                 srv_spoolss_replycloseprinter(snum,
216                                                 &Printer->notify.client_hnd);
217                 }
218         }
219
220         Printer->notify.flags=0;
221         Printer->notify.options=0;
222         Printer->notify.localmachine[0]='\0';
223         Printer->notify.printerlocal=0;
224         TALLOC_FREE(Printer->notify.option);
225         Printer->notify.client_connected = false;
226
227         TALLOC_FREE(Printer->devmode);
228
229         /* Remove from the internal list. */
230         DLIST_REMOVE(printers_list, Printer);
231         return 0;
232 }
233
234 /****************************************************************************
235   find printer index by handle
236 ****************************************************************************/
237
238 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
239                                                 struct policy_handle *hnd)
240 {
241         Printer_entry *find_printer = NULL;
242
243         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
244                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
245                 return NULL;
246         }
247
248         return find_printer;
249 }
250
251 /****************************************************************************
252  Close printer index by handle.
253 ****************************************************************************/
254
255 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
256 {
257         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
258
259         if (!Printer) {
260                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
261                         OUR_HANDLE(hnd)));
262                 return false;
263         }
264
265         close_policy_hnd(p, hnd);
266
267         return true;
268 }
269
270 /****************************************************************************
271  Delete a printer given a handle.
272 ****************************************************************************/
273
274 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
275 {
276         char *cmd = lp_deleteprinter_cmd();
277         char *command = NULL;
278         int ret;
279         SE_PRIV se_printop = SE_PRINT_OPERATOR;
280         bool is_print_op = false;
281
282         /* can't fail if we don't try */
283
284         if ( !*cmd )
285                 return WERR_OK;
286
287         command = talloc_asprintf(ctx,
288                         "%s \"%s\"",
289                         cmd, sharename);
290         if (!command) {
291                 return WERR_NOMEM;
292         }
293         if ( token )
294                 is_print_op = user_has_privileges( token, &se_printop );
295
296         DEBUG(10,("Running [%s]\n", command));
297
298         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
299
300         if ( is_print_op )
301                 become_root();
302
303         if ( (ret = smbrun(command, NULL)) == 0 ) {
304                 /* Tell everyone we updated smb.conf. */
305                 message_send_all(smbd_messaging_context(),
306                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
307         }
308
309         if ( is_print_op )
310                 unbecome_root();
311
312         /********** END SePrintOperatorPrivlege BLOCK **********/
313
314         DEBUGADD(10,("returned [%d]\n", ret));
315
316         TALLOC_FREE(command);
317
318         if (ret != 0)
319                 return WERR_BADFID; /* What to return here? */
320
321         /* go ahead and re-read the services immediately */
322         become_root();
323         reload_services(false);
324         unbecome_root();
325
326         if ( lp_servicenumber( sharename )  > 0 )
327                 return WERR_ACCESS_DENIED;
328
329         return WERR_OK;
330 }
331
332 /****************************************************************************
333  Delete a printer given a handle.
334 ****************************************************************************/
335
336 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
337 {
338         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
339         WERROR result;
340
341         if (!Printer) {
342                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
343                         OUR_HANDLE(hnd)));
344                 return WERR_BADFID;
345         }
346
347         /*
348          * It turns out that Windows allows delete printer on a handle
349          * opened by an admin user, then used on a pipe handle created
350          * by an anonymous user..... but they're working on security.... riiight !
351          * JRA.
352          */
353
354         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
355                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
356                 return WERR_ACCESS_DENIED;
357         }
358
359         /* this does not need a become root since the access check has been
360            done on the handle already */
361
362         result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
363                                            Printer->sharename, "");
364         if (!W_ERROR_IS_OK(result)) {
365                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
366                 return WERR_BADFID;
367         }
368
369         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
370                                    Printer->sharename );
371 }
372
373 /****************************************************************************
374  Return the snum of a printer corresponding to an handle.
375 ****************************************************************************/
376
377 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
378                              int *number, struct share_params **params)
379 {
380         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
381
382         if (!Printer) {
383                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
384                         OUR_HANDLE(hnd)));
385                 return false;
386         }
387
388         switch (Printer->printer_type) {
389                 case SPLHND_PRINTER:
390                         DEBUG(4,("short name:%s\n", Printer->sharename));
391                         *number = print_queue_snum(Printer->sharename);
392                         return (*number != -1);
393                 case SPLHND_SERVER:
394                         return false;
395                 default:
396                         return false;
397         }
398 }
399
400 /****************************************************************************
401  Set printer handle type.
402  Check if it's \\server or \\server\printer
403 ****************************************************************************/
404
405 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
406 {
407         DEBUG(3,("Setting printer type=%s\n", handlename));
408
409         if ( strlen(handlename) < 3 ) {
410                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
411                 return false;
412         }
413
414         /* it's a print server */
415         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
416                 DEBUGADD(4,("Printer is a print server\n"));
417                 Printer->printer_type = SPLHND_SERVER;
418         }
419         /* it's a printer (set_printer_hnd_name() will handle port monitors */
420         else {
421                 DEBUGADD(4,("Printer is a printer\n"));
422                 Printer->printer_type = SPLHND_PRINTER;
423         }
424
425         return true;
426 }
427
428 /****************************************************************************
429  Set printer handle name..  Accept names like \\server, \\server\printer,
430  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
431  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
432  XcvDataPort() interface.
433 ****************************************************************************/
434
435 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
436                                  struct auth_serversupplied_info *server_info,
437                                  Printer_entry *Printer,
438                                  const char *handlename)
439 {
440         int snum;
441         int n_services=lp_numservices();
442         char *aprinter;
443         const char *printername;
444         const char *servername;
445         fstring sname;
446         bool found = false;
447         struct spoolss_PrinterInfo2 *info2 = NULL;
448         WERROR result;
449
450         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
451                 (unsigned long)strlen(handlename)));
452
453         aprinter = CONST_DISCARD(char *, handlename);
454         if ( *handlename == '\\' ) {
455                 servername = canon_servername(handlename);
456                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
457                         *aprinter = '\0';
458                         aprinter++;
459                 }
460                 if (!is_myname_or_ipaddr(servername)) {
461                         return false;
462                 }
463
464                 fstrcpy(Printer->servername, servername);
465         }
466
467         if (Printer->printer_type == SPLHND_SERVER) {
468                 return true;
469         }
470
471         if (Printer->printer_type != SPLHND_PRINTER) {
472                 return false;
473         }
474
475         DEBUGADD(5, ("searching for [%s]\n", aprinter));
476
477         /* check for the Port Monitor Interface */
478         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
479                 Printer->printer_type = SPLHND_PORTMON_TCP;
480                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
481                 found = true;
482         }
483         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
484                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
485                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
486                 found = true;
487         }
488
489         /* Search all sharenames first as this is easier than pulling
490            the printer_info_2 off of disk. Don't use find_service() since
491            that calls out to map_username() */
492
493         /* do another loop to look for printernames */
494         for (snum = 0; !found && snum < n_services; snum++) {
495                 const char *printer = lp_const_servicename(snum);
496
497                 /* no point going on if this is not a printer */
498                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
499                         continue;
500                 }
501
502                 /* ignore [printers] share */
503                 if (strequal(printer, "printers")) {
504                         continue;
505                 }
506
507                 fstrcpy(sname, printer);
508                 if (strequal(aprinter, printer)) {
509                         found = true;
510                         break;
511                 }
512
513                 /* no point looking up the printer object if
514                    we aren't allowing printername != sharename */
515                 if (lp_force_printername(snum)) {
516                         continue;
517                 }
518
519                 result = winreg_get_printer(mem_ctx,
520                                             server_info,
521                                             servername,
522                                             sname,
523                                             &info2);
524                 if ( !W_ERROR_IS_OK(result) ) {
525                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
526                                  sname, win_errstr(result)));
527                         continue;
528                 }
529
530                 printername = strrchr(info2->printername, '\\');
531                 if (printername == NULL) {
532                         printername = info2->printername;
533                 } else {
534                         printername++;
535                 }
536
537                 if (strequal(printername, aprinter)) {
538                         found = true;
539                         break;
540                 }
541
542                 DEBUGADD(10, ("printername: %s\n", printername));
543
544                 TALLOC_FREE(info2);
545         }
546
547         if ( !found ) {
548                 DEBUGADD(4,("Printer not found\n"));
549                 return false;
550         }
551
552         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
553
554         fstrcpy(Printer->sharename, sname);
555
556         return true;
557 }
558
559 /****************************************************************************
560  Find first available printer slot. creates a printer handle for you.
561  ****************************************************************************/
562
563 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
564                              const char *name, uint32_t access_granted)
565 {
566         Printer_entry *new_printer;
567
568         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
569
570         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
571         if (new_printer == NULL) {
572                 return false;
573         }
574         talloc_set_destructor(new_printer, printer_entry_destructor);
575
576         if (!create_policy_hnd(p, hnd, new_printer)) {
577                 TALLOC_FREE(new_printer);
578                 return false;
579         }
580
581         /* Add to the internal list. */
582         DLIST_ADD(printers_list, new_printer);
583
584         new_printer->notify.option=NULL;
585
586         if (!set_printer_hnd_printertype(new_printer, name)) {
587                 close_printer_handle(p, hnd);
588                 return false;
589         }
590
591         if (!set_printer_hnd_name(p->mem_ctx, p->server_info, new_printer, name)) {
592                 close_printer_handle(p, hnd);
593                 return false;
594         }
595
596         new_printer->access_granted = access_granted;
597
598         DEBUG(5, ("%d printer handles active\n",
599                   (int)num_pipe_handles(p)));
600
601         return true;
602 }
603
604 /***************************************************************************
605  check to see if the client motify handle is monitoring the notification
606  given by (notify_type, notify_field).
607  **************************************************************************/
608
609 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
610                                       uint16_t notify_field)
611 {
612         return true;
613 }
614
615 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
616                                 uint16_t notify_field)
617 {
618         struct spoolss_NotifyOption *option = p->notify.option;
619         uint32_t i, j;
620
621         /*
622          * Flags should always be zero when the change notify
623          * is registered by the client's spooler.  A user Win32 app
624          * might use the flags though instead of the NOTIFY_OPTION_INFO
625          * --jerry
626          */
627
628         if (!option) {
629                 return false;
630         }
631
632         if (p->notify.flags)
633                 return is_monitoring_event_flags(
634                         p->notify.flags, notify_type, notify_field);
635
636         for (i = 0; i < option->count; i++) {
637
638                 /* Check match for notify_type */
639
640                 if (option->types[i].type != notify_type)
641                         continue;
642
643                 /* Check match for field */
644
645                 for (j = 0; j < option->types[i].count; j++) {
646                         if (option->types[i].fields[j].field == notify_field) {
647                                 return true;
648                         }
649                 }
650         }
651
652         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
653                    p->servername, p->sharename, notify_type, notify_field));
654
655         return false;
656 }
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
659         _data->data.integer[0] = _integer; \
660         _data->data.integer[1] = 0;
661
662
663 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
664         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
665         if (!_data->data.string.string) {\
666                 _data->data.string.size = 0; \
667         } \
668         _data->data.string.size = strlen_m_term(_p) * 2;
669
670 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
671         _data->data.devmode.devmode = _devmode;
672
673 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
674         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
675         if (!_data->data.sd.sd) { \
676                 _data->data.sd.sd_size = 0; \
677         } \
678         _data->data.sd.sd_size = \
679                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
680
681 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
682                                    struct tm *t,
683                                    const char **pp,
684                                    uint32_t *plen)
685 {
686         struct spoolss_Time st;
687         uint32_t len = 16;
688         char *p;
689
690         if (!init_systemtime(&st, t)) {
691                 return;
692         }
693
694         p = talloc_array(mem_ctx, char, len);
695         if (!p) {
696                 return;
697         }
698
699         /*
700          * Systemtime must be linearized as a set of UINT16's.
701          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
702          */
703
704         SSVAL(p, 0, st.year);
705         SSVAL(p, 2, st.month);
706         SSVAL(p, 4, st.day_of_week);
707         SSVAL(p, 6, st.day);
708         SSVAL(p, 8, st.hour);
709         SSVAL(p, 10, st.minute);
710         SSVAL(p, 12, st.second);
711         SSVAL(p, 14, st.millisecond);
712
713         *pp = p;
714         *plen = len;
715 }
716
717 /* Convert a notification message to a struct spoolss_Notify */
718
719 static void notify_one_value(struct spoolss_notify_msg *msg,
720                              struct spoolss_Notify *data,
721                              TALLOC_CTX *mem_ctx)
722 {
723         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
724 }
725
726 static void notify_string(struct spoolss_notify_msg *msg,
727                           struct spoolss_Notify *data,
728                           TALLOC_CTX *mem_ctx)
729 {
730         /* The length of the message includes the trailing \0 */
731
732         data->data.string.size = msg->len * 2;
733         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
734         if (!data->data.string.string) {
735                 data->data.string.size = 0;
736                 return;
737         }
738 }
739
740 static void notify_system_time(struct spoolss_notify_msg *msg,
741                                struct spoolss_Notify *data,
742                                TALLOC_CTX *mem_ctx)
743 {
744         data->data.string.string = NULL;
745         data->data.string.size = 0;
746
747         if (msg->len != sizeof(time_t)) {
748                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
749                           msg->len));
750                 return;
751         }
752
753         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
754                                &data->data.string.string,
755                                &data->data.string.size);
756 }
757
758 struct notify2_message_table {
759         const char *name;
760         void (*fn)(struct spoolss_notify_msg *msg,
761                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
762 };
763
764 static struct notify2_message_table printer_notify_table[] = {
765         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
766         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
767         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
768         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
769         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
770         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
771         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
772         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
773         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
774         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
775         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
776         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
777         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
778         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
779         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
780         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
781         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
782         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
783         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
784 };
785
786 static struct notify2_message_table job_notify_table[] = {
787         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
788         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
789         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
790         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
791         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
792         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
793         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
794         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
795         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
796         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
797         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
798         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
799         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
800         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
801         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
802         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
803         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
804         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
805         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
806         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
807         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
808         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
809         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
810         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
811 };
812
813
814 /***********************************************************************
815  Allocate talloc context for container object
816  **********************************************************************/
817
818 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
819 {
820         if ( !ctr )
821                 return;
822
823         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
824
825         return;
826 }
827
828 /***********************************************************************
829  release all allocated memory and zero out structure
830  **********************************************************************/
831
832 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 {
834         if ( !ctr )
835                 return;
836
837         if ( ctr->ctx )
838                 talloc_destroy(ctr->ctx);
839
840         ZERO_STRUCTP(ctr);
841
842         return;
843 }
844
845 /***********************************************************************
846  **********************************************************************/
847
848 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
849 {
850         if ( !ctr )
851                 return NULL;
852
853         return ctr->ctx;
854 }
855
856 /***********************************************************************
857  **********************************************************************/
858
859 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
860 {
861         if ( !ctr || !ctr->msg_groups )
862                 return NULL;
863
864         if ( idx >= ctr->num_groups )
865                 return NULL;
866
867         return &ctr->msg_groups[idx];
868
869 }
870
871 /***********************************************************************
872  How many groups of change messages do we have ?
873  **********************************************************************/
874
875 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
876 {
877         if ( !ctr )
878                 return 0;
879
880         return ctr->num_groups;
881 }
882
883 /***********************************************************************
884  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
885  **********************************************************************/
886
887 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
888 {
889         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
890         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
891         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
892         int                             i, new_slot;
893
894         if ( !ctr || !msg )
895                 return 0;
896
897         /* loop over all groups looking for a matching printer name */
898
899         for ( i=0; i<ctr->num_groups; i++ ) {
900                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
901                         break;
902         }
903
904         /* add a new group? */
905
906         if ( i == ctr->num_groups ) {
907                 ctr->num_groups++;
908
909                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
910                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
911                         return 0;
912                 }
913                 ctr->msg_groups = groups;
914
915                 /* clear the new entry and set the printer name */
916
917                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
918                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
919         }
920
921         /* add the change messages; 'i' is the correct index now regardless */
922
923         msg_grp = &ctr->msg_groups[i];
924
925         msg_grp->num_msgs++;
926
927         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
928                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
929                 return 0;
930         }
931         msg_grp->msgs = msg_list;
932
933         new_slot = msg_grp->num_msgs-1;
934         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
935
936         /* need to allocate own copy of data */
937
938         if ( msg->len != 0 )
939                 msg_grp->msgs[new_slot].notify.data = (char *)
940                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
941
942         return ctr->num_groups;
943 }
944
945 static void construct_info_data(struct spoolss_Notify *info_data,
946                                 enum spoolss_NotifyType type,
947                                 uint16_t field, int id);
948
949 /***********************************************************************
950  Send a change notication message on all handles which have a call
951  back registered
952  **********************************************************************/
953
954 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
955 {
956         Printer_entry            *p;
957         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
958         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
959         SPOOLSS_NOTIFY_MSG       *messages;
960         int                      sending_msg_count;
961
962         if ( !msg_group ) {
963                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
964                 return;
965         }
966
967         messages = msg_group->msgs;
968
969         if ( !messages ) {
970                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
971                 return;
972         }
973
974         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
975
976         /* loop over all printers */
977
978         for (p = printers_list; p; p = p->next) {
979                 struct spoolss_Notify *notifies;
980                 uint32_t count = 0;
981                 uint32_t id;
982                 int     i;
983
984                 /* Is there notification on this handle? */
985
986                 if ( !p->notify.client_connected )
987                         continue;
988
989                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
990
991                 /* For this printer?  Print servers always receive
992                    notifications. */
993
994                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
995                     ( !strequal(msg_group->printername, p->sharename) ) )
996                         continue;
997
998                 DEBUG(10,("Our printer\n"));
999
1000                 /* allocate the max entries possible */
1001
1002                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1003                 if (!notifies) {
1004                         return;
1005                 }
1006
1007                 /* build the array of change notifications */
1008
1009                 sending_msg_count = 0;
1010
1011                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1012                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1013
1014                         /* Are we monitoring this event? */
1015
1016                         if (!is_monitoring_event(p, msg->type, msg->field))
1017                                 continue;
1018
1019                         sending_msg_count++;
1020
1021
1022                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1023                                 msg->type, msg->field, p->sharename));
1024
1025                         /*
1026                          * if the is a printer notification handle and not a job notification
1027                          * type, then set the id to 0.  Other wise just use what was specified
1028                          * in the message.
1029                          *
1030                          * When registering change notification on a print server handle
1031                          * we always need to send back the id (snum) matching the printer
1032                          * for which the change took place.  For change notify registered
1033                          * on a printer handle, this does not matter and the id should be 0.
1034                          *
1035                          * --jerry
1036                          */
1037
1038                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1039                                 id = 0;
1040                         else
1041                                 id = msg->id;
1042
1043
1044                         /* Convert unix jobid to smb jobid */
1045
1046                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1047                                 id = sysjob_to_jobid(msg->id);
1048
1049                                 if (id == -1) {
1050                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1051                                         goto done;
1052                                 }
1053                         }
1054
1055                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1056
1057                         switch(msg->type) {
1058                         case PRINTER_NOTIFY_TYPE:
1059                                 if ( printer_notify_table[msg->field].fn )
1060                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1061                                 break;
1062
1063                         case JOB_NOTIFY_TYPE:
1064                                 if ( job_notify_table[msg->field].fn )
1065                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1066                                 break;
1067
1068                         default:
1069                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1070                                 goto done;
1071                         }
1072
1073                         count++;
1074                 }
1075
1076                 if ( sending_msg_count ) {
1077                         NTSTATUS status;
1078                         WERROR werr;
1079                         union spoolss_ReplyPrinterInfo info;
1080                         struct spoolss_NotifyInfo info0;
1081                         uint32_t reply_result;
1082
1083                         info0.version   = 0x2;
1084                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1085                         info0.count     = count;
1086                         info0.notifies  = notifies;
1087
1088                         info.info0 = &info0;
1089
1090                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1091                                                                      &p->notify.client_hnd,
1092                                                                      p->notify.change, /* color */
1093                                                                      p->notify.flags,
1094                                                                      &reply_result,
1095                                                                      0, /* reply_type, must be 0 */
1096                                                                      info,
1097                                                                      &werr);
1098                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1099                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1100                                         notify_cli_pipe->srv_name_slash,
1101                                         win_errstr(werr)));
1102                         }
1103                         switch (reply_result) {
1104                                 case 0:
1105                                         break;
1106                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1107                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1108                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1109                                         break;
1110                                 default:
1111                                         break;
1112                         }
1113                 }
1114         }
1115
1116 done:
1117         DEBUG(8,("send_notify2_changes: Exit...\n"));
1118         return;
1119 }
1120
1121 /***********************************************************************
1122  **********************************************************************/
1123
1124 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1125 {
1126
1127         uint32_t tv_sec, tv_usec;
1128         size_t offset = 0;
1129
1130         /* Unpack message */
1131
1132         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1133                              msg->printer);
1134
1135         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1136                                 &tv_sec, &tv_usec,
1137                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1138
1139         if (msg->len == 0)
1140                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1141                            &msg->notify.value[0], &msg->notify.value[1]);
1142         else
1143                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1144                            &msg->len, &msg->notify.data);
1145
1146         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1147                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1148
1149         tv->tv_sec = tv_sec;
1150         tv->tv_usec = tv_usec;
1151
1152         if (msg->len == 0)
1153                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1154                           msg->notify.value[1]));
1155         else
1156                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1157
1158         return true;
1159 }
1160
1161 /********************************************************************
1162  Receive a notify2 message list
1163  ********************************************************************/
1164
1165 static void receive_notify2_message_list(struct messaging_context *msg,
1166                                          void *private_data,
1167                                          uint32_t msg_type,
1168                                          struct server_id server_id,
1169                                          DATA_BLOB *data)
1170 {
1171         size_t                  msg_count, i;
1172         char                    *buf = (char *)data->data;
1173         char                    *msg_ptr;
1174         size_t                  msg_len;
1175         SPOOLSS_NOTIFY_MSG      notify;
1176         SPOOLSS_NOTIFY_MSG_CTR  messages;
1177         int                     num_groups;
1178
1179         if (data->length < 4) {
1180                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1181                 return;
1182         }
1183
1184         msg_count = IVAL(buf, 0);
1185         msg_ptr = buf + 4;
1186
1187         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1188
1189         if (msg_count == 0) {
1190                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1191                 return;
1192         }
1193
1194         /* initialize the container */
1195
1196         ZERO_STRUCT( messages );
1197         notify_msg_ctr_init( &messages );
1198
1199         /*
1200          * build message groups for each printer identified
1201          * in a change_notify msg.  Remember that a PCN message
1202          * includes the handle returned for the srv_spoolss_replyopenprinter()
1203          * call.  Therefore messages are grouped according to printer handle.
1204          */
1205
1206         for ( i=0; i<msg_count; i++ ) {
1207                 struct timeval msg_tv;
1208
1209                 if (msg_ptr + 4 - buf > data->length) {
1210                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1211                         return;
1212                 }
1213
1214                 msg_len = IVAL(msg_ptr,0);
1215                 msg_ptr += 4;
1216
1217                 if (msg_ptr + msg_len - buf > data->length) {
1218                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1219                         return;
1220                 }
1221
1222                 /* unpack messages */
1223
1224                 ZERO_STRUCT( notify );
1225                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1226                 msg_ptr += msg_len;
1227
1228                 /* add to correct list in container */
1229
1230                 notify_msg_ctr_addmsg( &messages, &notify );
1231
1232                 /* free memory that might have been allocated by notify2_unpack_msg() */
1233
1234                 if ( notify.len != 0 )
1235                         SAFE_FREE( notify.notify.data );
1236         }
1237
1238         /* process each group of messages */
1239
1240         num_groups = notify_msg_ctr_numgroups( &messages );
1241         for ( i=0; i<num_groups; i++ )
1242                 send_notify2_changes( &messages, i );
1243
1244
1245         /* cleanup */
1246
1247         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1248                 (uint32_t)msg_count ));
1249
1250         notify_msg_ctr_destroy( &messages );
1251
1252         return;
1253 }
1254
1255 /********************************************************************
1256  Send a message to ourself about new driver being installed
1257  so we can upgrade the information for each printer bound to this
1258  driver
1259  ********************************************************************/
1260
1261 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1262 {
1263         int len = strlen(drivername);
1264
1265         if (!len)
1266                 return false;
1267
1268         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1269                 drivername));
1270
1271         messaging_send_buf(smbd_messaging_context(),
1272                            messaging_server_id(smbd_messaging_context()),
1273                            MSG_PRINTER_DRVUPGRADE,
1274                            (uint8_t *)drivername, len+1);
1275
1276         return true;
1277 }
1278
1279 /**********************************************************************
1280  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1281  over all printers, upgrading ones as necessary
1282  **********************************************************************/
1283
1284 void do_drv_upgrade_printer(struct messaging_context *msg,
1285                             void *private_data,
1286                             uint32_t msg_type,
1287                             struct server_id server_id,
1288                             DATA_BLOB *data)
1289 {
1290         TALLOC_CTX *tmp_ctx;
1291         struct auth_serversupplied_info *server_info = NULL;
1292         struct spoolss_PrinterInfo2 *pinfo2;
1293         NTSTATUS status;
1294         WERROR result;
1295         const char *drivername;
1296         int snum;
1297         int n_services = lp_numservices();
1298         size_t len;
1299
1300         tmp_ctx = talloc_new(NULL);
1301         if (!tmp_ctx) return;
1302
1303         status = make_server_info_system(tmp_ctx, &server_info);
1304         if (!NT_STATUS_IS_OK(status)) {
1305                 DEBUG(0, ("do_drv_upgrade_printer: "
1306                           "Could not create system server_info\n"));
1307                 goto done;
1308         }
1309
1310         len = MIN(data->length,sizeof(drivername)-1);
1311         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1312         if (!drivername) {
1313                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1314                 goto done;
1315         }
1316
1317         DEBUG(10, ("do_drv_upgrade_printer: "
1318                    "Got message for new driver [%s]\n", drivername));
1319
1320         /* Iterate the printer list */
1321
1322         for (snum = 0; snum < n_services; snum++) {
1323                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1324                         continue;
1325                 }
1326
1327                 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1328                                             lp_const_servicename(snum),
1329                                             &pinfo2);
1330
1331                 if (!W_ERROR_IS_OK(result)) {
1332                         continue;
1333                 }
1334
1335                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1336                         continue;
1337                 }
1338
1339                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1340
1341                 /* all we care about currently is the change_id */
1342                 result = winreg_printer_update_changeid(tmp_ctx,
1343                                                         server_info,
1344                                                         pinfo2->printername);
1345
1346                 if (!W_ERROR_IS_OK(result)) {
1347                         DEBUG(3, ("do_drv_upgrade_printer: "
1348                                   "Failed to update changeid [%s]\n",
1349                                   win_errstr(result)));
1350                 }
1351         }
1352
1353         /* all done */
1354 done:
1355         talloc_free(tmp_ctx);
1356 }
1357
1358 /********************************************************************
1359  Update the cache for all printq's with a registered client
1360  connection
1361  ********************************************************************/
1362
1363 void update_monitored_printq_cache( void )
1364 {
1365         Printer_entry *printer = printers_list;
1366         int snum;
1367
1368         /* loop through all printers and update the cache where
1369            client_connected == true */
1370         while ( printer )
1371         {
1372                 if ( (printer->printer_type == SPLHND_PRINTER)
1373                         && printer->notify.client_connected )
1374                 {
1375                         snum = print_queue_snum(printer->sharename);
1376                         print_queue_status( snum, NULL, NULL );
1377                 }
1378
1379                 printer = printer->next;
1380         }
1381
1382         return;
1383 }
1384
1385 /****************************************************************
1386  _spoolss_OpenPrinter
1387 ****************************************************************/
1388
1389 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1390                             struct spoolss_OpenPrinter *r)
1391 {
1392         struct spoolss_OpenPrinterEx e;
1393         WERROR werr;
1394
1395         ZERO_STRUCT(e.in.userlevel);
1396
1397         e.in.printername        = r->in.printername;
1398         e.in.datatype           = r->in.datatype;
1399         e.in.devmode_ctr        = r->in.devmode_ctr;
1400         e.in.access_mask        = r->in.access_mask;
1401         e.in.level              = 0;
1402
1403         e.out.handle            = r->out.handle;
1404
1405         werr = _spoolss_OpenPrinterEx(p, &e);
1406
1407         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1408                 /* OpenPrinterEx returns this for a bad
1409                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1410                  * instead.
1411                  */
1412                 werr = WERR_INVALID_PRINTER_NAME;
1413         }
1414
1415         return werr;
1416 }
1417
1418 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1419                               struct spoolss_DeviceMode *orig,
1420                               struct spoolss_DeviceMode **dest)
1421 {
1422         struct spoolss_DeviceMode *dm;
1423
1424         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1425         if (!dm) {
1426                 return WERR_NOMEM;
1427         }
1428
1429         /* copy all values, then duplicate strings and structs */
1430         *dm = *orig;
1431
1432         dm->devicename = talloc_strdup(dm, orig->devicename);
1433         if (!dm->devicename) {
1434                 return WERR_NOMEM;
1435         }
1436         dm->formname = talloc_strdup(dm, orig->formname);
1437         if (!dm->formname) {
1438                 return WERR_NOMEM;
1439         }
1440         if (orig->driverextra_data.data) {
1441                 dm->driverextra_data.data =
1442                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1443                                         orig->driverextra_data.length);
1444                 if (!dm->driverextra_data.data) {
1445                         return WERR_NOMEM;
1446                 }
1447         }
1448
1449         *dest = dm;
1450         return WERR_OK;
1451 }
1452
1453 /****************************************************************
1454  _spoolss_OpenPrinterEx
1455 ****************************************************************/
1456
1457 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1458                               struct spoolss_OpenPrinterEx *r)
1459 {
1460         int snum;
1461         Printer_entry *Printer=NULL;
1462
1463         if (!r->in.printername) {
1464                 return WERR_INVALID_PARAM;
1465         }
1466
1467         /* some sanity check because you can open a printer or a print server */
1468         /* aka: \\server\printer or \\server */
1469
1470         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1471
1472         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1473                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1474                         " for printer %s\n", r->in.printername));
1475                 ZERO_STRUCTP(r->out.handle);
1476                 return WERR_INVALID_PARAM;
1477         }
1478
1479         Printer = find_printer_index_by_hnd(p, r->out.handle);
1480         if ( !Printer ) {
1481                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1482                         "handle we created for printer %s\n", r->in.printername));
1483                 close_printer_handle(p, r->out.handle);
1484                 ZERO_STRUCTP(r->out.handle);
1485                 return WERR_INVALID_PARAM;
1486         }
1487
1488         /*
1489          * First case: the user is opening the print server:
1490          *
1491          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1492          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1493          *
1494          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1495          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1496          * or if the user is listed in the smb.conf printer admin parameter.
1497          *
1498          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1499          * client view printer folder, but does not show the MSAPW.
1500          *
1501          * Note: this test needs code to check access rights here too. Jeremy
1502          * could you look at this?
1503          *
1504          * Second case: the user is opening a printer:
1505          * NT doesn't let us connect to a printer if the connecting user
1506          * doesn't have print permission.
1507          *
1508          * Third case: user is opening a Port Monitor
1509          * access checks same as opening a handle to the print server.
1510          */
1511
1512         switch (Printer->printer_type )
1513         {
1514         case SPLHND_SERVER:
1515         case SPLHND_PORTMON_TCP:
1516         case SPLHND_PORTMON_LOCAL:
1517                 /* Printserver handles use global struct... */
1518
1519                 snum = -1;
1520
1521                 /* Map standard access rights to object specific access rights */
1522
1523                 se_map_standard(&r->in.access_mask,
1524                                 &printserver_std_mapping);
1525
1526                 /* Deny any object specific bits that don't apply to print
1527                    servers (i.e printer and job specific bits) */
1528
1529                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1530
1531                 if (r->in.access_mask &
1532                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1533                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1534                         close_printer_handle(p, r->out.handle);
1535                         ZERO_STRUCTP(r->out.handle);
1536                         return WERR_ACCESS_DENIED;
1537                 }
1538
1539                 /* Allow admin access */
1540
1541                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1542                 {
1543                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1544
1545                         if (!lp_ms_add_printer_wizard()) {
1546                                 close_printer_handle(p, r->out.handle);
1547                                 ZERO_STRUCTP(r->out.handle);
1548                                 return WERR_ACCESS_DENIED;
1549                         }
1550
1551                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1552                            and not a printer admin, then fail */
1553
1554                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1555                             !user_has_privileges(p->server_info->ptok,
1556                                                  &se_printop ) &&
1557                             !token_contains_name_in_list(
1558                                     uidtoname(p->server_info->utok.uid),
1559                                     p->server_info->info3->base.domain.string,
1560                                     NULL,
1561                                     p->server_info->ptok,
1562                                     lp_printer_admin(snum))) {
1563                                 close_printer_handle(p, r->out.handle);
1564                                 ZERO_STRUCTP(r->out.handle);
1565                                 return WERR_ACCESS_DENIED;
1566                         }
1567
1568                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1569                 }
1570                 else
1571                 {
1572                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1573                 }
1574
1575                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1576                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1577
1578                 /* We fall through to return WERR_OK */
1579                 break;
1580
1581         case SPLHND_PRINTER:
1582                 /* NT doesn't let us connect to a printer if the connecting user
1583                    doesn't have print permission.  */
1584
1585                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1586                         close_printer_handle(p, r->out.handle);
1587                         ZERO_STRUCTP(r->out.handle);
1588                         return WERR_BADFID;
1589                 }
1590
1591                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1592                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1593                 }
1594
1595                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1596
1597                 /* map an empty access mask to the minimum access mask */
1598                 if (r->in.access_mask == 0x0)
1599                         r->in.access_mask = PRINTER_ACCESS_USE;
1600
1601                 /*
1602                  * If we are not serving the printer driver for this printer,
1603                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1604                  * will keep NT clients happy  --jerry
1605                  */
1606
1607                 if (lp_use_client_driver(snum)
1608                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1609                 {
1610                         r->in.access_mask = PRINTER_ACCESS_USE;
1611                 }
1612
1613                 /* check smb.conf parameters and the the sec_desc */
1614
1615                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1616                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1617                         ZERO_STRUCTP(r->out.handle);
1618                         return WERR_ACCESS_DENIED;
1619                 }
1620
1621                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1622                                    p->server_info->ptok, snum) ||
1623                     !print_access_check(p->server_info, snum,
1624                                         r->in.access_mask)) {
1625                         DEBUG(3, ("access DENIED for printer open\n"));
1626                         close_printer_handle(p, r->out.handle);
1627                         ZERO_STRUCTP(r->out.handle);
1628                         return WERR_ACCESS_DENIED;
1629                 }
1630
1631                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1632                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1633                         close_printer_handle(p, r->out.handle);
1634                         ZERO_STRUCTP(r->out.handle);
1635                         return WERR_ACCESS_DENIED;
1636                 }
1637
1638                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1639                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1640                 else
1641                         r->in.access_mask = PRINTER_ACCESS_USE;
1642
1643                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1644                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1645
1646                 winreg_create_printer(p->mem_ctx,
1647                                       p->server_info,
1648                                       Printer->servername,
1649                                       lp_const_servicename(snum));
1650
1651                 break;
1652
1653         default:
1654                 /* sanity check to prevent programmer error */
1655                 ZERO_STRUCTP(r->out.handle);
1656                 return WERR_BADFID;
1657         }
1658
1659         Printer->access_granted = r->in.access_mask;
1660
1661         /*
1662          * If the client sent a devmode in the OpenPrinter() call, then
1663          * save it here in case we get a job submission on this handle
1664          */
1665
1666          if ((Printer->printer_type != SPLHND_SERVER) &&
1667              r->in.devmode_ctr.devmode) {
1668                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1669                                 &Printer->devmode);
1670          }
1671
1672 #if 0   /* JERRY -- I'm doubtful this is really effective */
1673         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1674            optimization in Windows 2000 clients  --jerry */
1675
1676         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1677                 && (RA_WIN2K == get_remote_arch()) )
1678         {
1679                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1680                 sys_usleep( 500000 );
1681         }
1682 #endif
1683
1684         return WERR_OK;
1685 }
1686
1687 /****************************************************************
1688  _spoolss_ClosePrinter
1689 ****************************************************************/
1690
1691 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1692                              struct spoolss_ClosePrinter *r)
1693 {
1694         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1695
1696         if (Printer && Printer->document_started) {
1697                 struct spoolss_EndDocPrinter e;
1698
1699                 e.in.handle = r->in.handle;
1700
1701                 _spoolss_EndDocPrinter(p, &e);
1702         }
1703
1704         if (!close_printer_handle(p, r->in.handle))
1705                 return WERR_BADFID;
1706
1707         /* clear the returned printer handle.  Observed behavior
1708            from Win2k server.  Don't think this really matters.
1709            Previous code just copied the value of the closed
1710            handle.    --jerry */
1711
1712         ZERO_STRUCTP(r->out.handle);
1713
1714         return WERR_OK;
1715 }
1716
1717 /****************************************************************
1718  _spoolss_DeletePrinter
1719 ****************************************************************/
1720
1721 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1722                               struct spoolss_DeletePrinter *r)
1723 {
1724         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1725         WERROR result;
1726         int snum;
1727
1728         if (Printer && Printer->document_started) {
1729                 struct spoolss_EndDocPrinter e;
1730
1731                 e.in.handle = r->in.handle;
1732
1733                 _spoolss_EndDocPrinter(p, &e);
1734         }
1735
1736         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1737                 winreg_delete_printer_key(p->mem_ctx,
1738                                           p->server_info,
1739                                           lp_const_servicename(snum),
1740                                           "");
1741         }
1742
1743         result = delete_printer_handle(p, r->in.handle);
1744
1745         return result;
1746 }
1747
1748 /*******************************************************************
1749  * static function to lookup the version id corresponding to an
1750  * long architecture string
1751  ******************************************************************/
1752
1753 static const struct print_architecture_table_node archi_table[]= {
1754
1755         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1756         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1757         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1758         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1759         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1760         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1761         {"Windows x64",          SPL_ARCH_X64,          3 },
1762         {NULL,                   "",            -1 }
1763 };
1764
1765 static int get_version_id(const char *arch)
1766 {
1767         int i;
1768
1769         for (i=0; archi_table[i].long_archi != NULL; i++)
1770         {
1771                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1772                         return (archi_table[i].version);
1773         }
1774
1775         return -1;
1776 }
1777
1778 /****************************************************************
1779  _spoolss_DeletePrinterDriver
1780 ****************************************************************/
1781
1782 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1783                                     struct spoolss_DeletePrinterDriver *r)
1784 {
1785
1786         struct spoolss_DriverInfo8 *info = NULL;
1787         struct spoolss_DriverInfo8 *info_win2k = NULL;
1788         int                             version;
1789         WERROR                          status;
1790         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1791
1792         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1793            and not a printer admin, then fail */
1794
1795         if ( (p->server_info->utok.uid != sec_initial_uid())
1796                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1797                 && !token_contains_name_in_list(
1798                         uidtoname(p->server_info->utok.uid),
1799                         p->server_info->info3->base.domain.string,
1800                         NULL,
1801                         p->server_info->ptok,
1802                         lp_printer_admin(-1)) )
1803         {
1804                 return WERR_ACCESS_DENIED;
1805         }
1806
1807         /* check that we have a valid driver name first */
1808
1809         if ((version = get_version_id(r->in.architecture)) == -1)
1810                 return WERR_INVALID_ENVIRONMENT;
1811
1812         status = winreg_get_driver(p->mem_ctx, p->server_info,
1813                                    r->in.architecture, r->in.driver,
1814                                    version, &info);
1815         if (!W_ERROR_IS_OK(status)) {
1816                 /* try for Win2k driver if "Windows NT x86" */
1817
1818                 if ( version == 2 ) {
1819                         version = 3;
1820
1821                         status = winreg_get_driver(p->mem_ctx, p->server_info,
1822                                                    r->in.architecture,
1823                                                    r->in.driver,
1824                                                    version, &info);
1825                         if (!W_ERROR_IS_OK(status)) {
1826                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1827                                 goto done;
1828                         }
1829                 }
1830                 /* otherwise it was a failure */
1831                 else {
1832                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1833                         goto done;
1834                 }
1835
1836         }
1837
1838         if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
1839                 status = WERR_PRINTER_DRIVER_IN_USE;
1840                 goto done;
1841         }
1842
1843         if (version == 2) {
1844                 status = winreg_get_driver(p->mem_ctx, p->server_info,
1845                                            r->in.architecture,
1846                                            r->in.driver, 3, &info_win2k);
1847                 if (W_ERROR_IS_OK(status)) {
1848                         /* if we get to here, we now have 2 driver info structures to remove */
1849                         /* remove the Win2k driver first*/
1850
1851                         status = winreg_del_driver(p->mem_ctx,
1852                                                    p->server_info,
1853                                                    info_win2k, 3);
1854                         talloc_free(info_win2k);
1855
1856                         /* this should not have failed---if it did, report to client */
1857                         if (!W_ERROR_IS_OK(status)) {
1858                                 goto done;
1859                         }
1860                 }
1861         }
1862
1863         status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
1864
1865 done:
1866         talloc_free(info);
1867
1868         return status;
1869 }
1870
1871 /****************************************************************
1872  _spoolss_DeletePrinterDriverEx
1873 ****************************************************************/
1874
1875 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1876                                       struct spoolss_DeletePrinterDriverEx *r)
1877 {
1878         struct spoolss_DriverInfo8      *info = NULL;
1879         struct spoolss_DriverInfo8      *info_win2k = NULL;
1880         int                             version;
1881         bool                            delete_files;
1882         WERROR                          status;
1883         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1884
1885         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1886            and not a printer admin, then fail */
1887
1888         if ( (p->server_info->utok.uid != sec_initial_uid())
1889                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1890                 && !token_contains_name_in_list(
1891                         uidtoname(p->server_info->utok.uid),
1892                         p->server_info->info3->base.domain.string,
1893                         NULL,
1894                         p->server_info->ptok, lp_printer_admin(-1)) )
1895         {
1896                 return WERR_ACCESS_DENIED;
1897         }
1898
1899         /* check that we have a valid driver name first */
1900         if ((version = get_version_id(r->in.architecture)) == -1) {
1901                 /* this is what NT returns */
1902                 return WERR_INVALID_ENVIRONMENT;
1903         }
1904
1905         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1906                 version = r->in.version;
1907
1908         status = winreg_get_driver(p->mem_ctx, p->server_info,
1909                                    r->in.architecture, r->in.driver,
1910                                    version, &info);
1911         if (!W_ERROR_IS_OK(status)) {
1912                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1913
1914                 /*
1915                  * if the client asked for a specific version,
1916                  * or this is something other than Windows NT x86,
1917                  * then we've failed
1918                  */
1919
1920                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1921                         goto done;
1922
1923                 /* try for Win2k driver if "Windows NT x86" */
1924
1925                 version = 3;
1926                 status = winreg_get_driver(info, p->server_info,
1927                                            r->in.architecture,
1928                                            r->in.driver,
1929                                            version, &info);
1930                 if (!W_ERROR_IS_OK(status)) {
1931                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1932                         goto done;
1933                 }
1934         }
1935
1936         if (printer_driver_in_use(info, p->server_info, info)) {
1937                 status = WERR_PRINTER_DRIVER_IN_USE;
1938                 goto done;
1939         }
1940
1941         /*
1942          * we have a couple of cases to consider.
1943          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
1944          *     then the delete should fail if **any** files overlap with
1945          *     other drivers
1946          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1947          *     non-overlapping files
1948          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1949          *     is set, the do not delete any files
1950          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1951          */
1952
1953         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1954
1955         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1956
1957         if (delete_files &&
1958             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1959             printer_driver_files_in_use(info, p->server_info, info)) {
1960                 /* no idea of the correct error here */
1961                 status = WERR_ACCESS_DENIED;
1962                 goto done;
1963         }
1964
1965
1966         /* also check for W32X86/3 if necessary; maybe we already have? */
1967
1968         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
1969                 status = winreg_get_driver(info, p->server_info,
1970                                            r->in.architecture,
1971                                            r->in.driver, 3, &info_win2k);
1972                 if (W_ERROR_IS_OK(status)) {
1973
1974                         if (delete_files &&
1975                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1976                             printer_driver_files_in_use(info, p->server_info,
1977                                                         info_win2k)) {
1978                                 /* no idea of the correct error here */
1979                                 talloc_free(info_win2k);
1980                                 status = WERR_ACCESS_DENIED;
1981                                 goto done;
1982                         }
1983
1984                         /* if we get to here, we now have 2 driver info structures to remove */
1985                         /* remove the Win2k driver first*/
1986
1987                         status = winreg_del_driver(info, p->server_info,
1988                                                    info_win2k, 3);
1989
1990                         /* this should not have failed---if it did, report to client */
1991
1992                         if (!W_ERROR_IS_OK(status)) {
1993                                 goto done;
1994                         }
1995
1996                         /*
1997                          * now delete any associated files if delete_files is
1998                          * true. Even if this part failes, we return succes
1999                          * because the driver doesn not exist any more
2000                          */
2001                         if (delete_files) {
2002                                 delete_driver_files(p->server_info,
2003                                                     info_win2k);
2004                         }
2005                 }
2006         }
2007
2008         status = winreg_del_driver(info, p->server_info, info, version);
2009         if (!W_ERROR_IS_OK(status)) {
2010                 goto done;
2011         }
2012
2013         /*
2014          * now delete any associated files if delete_files is
2015          * true. Even if this part failes, we return succes
2016          * because the driver doesn not exist any more
2017          */
2018         if (delete_files) {
2019                 delete_driver_files(p->server_info, info);
2020         }
2021
2022 done:
2023         talloc_free(info);
2024         return status;
2025 }
2026
2027
2028 /********************************************************************
2029  GetPrinterData on a printer server Handle.
2030 ********************************************************************/
2031
2032 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2033                                             const char *value,
2034                                             enum winreg_Type *type,
2035                                             union spoolss_PrinterData *data)
2036 {
2037         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2038
2039         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2040                 *type = REG_DWORD;
2041                 data->value = 0x00;
2042                 return WERR_OK;
2043         }
2044
2045         if (!StrCaseCmp(value, "BeepEnabled")) {
2046                 *type = REG_DWORD;
2047                 data->value = 0x00;
2048                 return WERR_OK;
2049         }
2050
2051         if (!StrCaseCmp(value, "EventLog")) {
2052                 *type = REG_DWORD;
2053                 /* formally was 0x1b */
2054                 data->value = 0x00;
2055                 return WERR_OK;
2056         }
2057
2058         if (!StrCaseCmp(value, "NetPopup")) {
2059                 *type = REG_DWORD;
2060                 data->value = 0x00;
2061                 return WERR_OK;
2062         }
2063
2064         if (!StrCaseCmp(value, "MajorVersion")) {
2065                 *type = REG_DWORD;
2066
2067                 /* Windows NT 4.0 seems to not allow uploading of drivers
2068                    to a server that reports 0x3 as the MajorVersion.
2069                    need to investigate more how Win2k gets around this .
2070                    -- jerry */
2071
2072                 if (RA_WINNT == get_remote_arch()) {
2073                         data->value = 0x02;
2074                 } else {
2075                         data->value = 0x03;
2076                 }
2077
2078                 return WERR_OK;
2079         }
2080
2081         if (!StrCaseCmp(value, "MinorVersion")) {
2082                 *type = REG_DWORD;
2083                 data->value = 0x00;
2084                 return WERR_OK;
2085         }
2086
2087         /* REG_BINARY
2088          *  uint32_t size        = 0x114
2089          *  uint32_t major       = 5
2090          *  uint32_t minor       = [0|1]
2091          *  uint32_t build       = [2195|2600]
2092          *  extra unicode string = e.g. "Service Pack 3"
2093          */
2094         if (!StrCaseCmp(value, "OSVersion")) {
2095                 DATA_BLOB blob;
2096                 enum ndr_err_code ndr_err;
2097                 struct spoolss_OSVersion os;
2098
2099                 os.major                = 5;    /* Windows 2000 == 5.0 */
2100                 os.minor                = 0;
2101                 os.build                = 2195; /* build */
2102                 os.extra_string         = "";   /* leave extra string empty */
2103
2104                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2105                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2106                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2107                         return WERR_GENERAL_FAILURE;
2108                 }
2109
2110                 *type = REG_BINARY;
2111                 data->binary = blob;
2112
2113                 return WERR_OK;
2114         }
2115
2116
2117         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2118                 *type = REG_SZ;
2119
2120                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2121                 W_ERROR_HAVE_NO_MEMORY(data->string);
2122
2123                 return WERR_OK;
2124         }
2125
2126         if (!StrCaseCmp(value, "Architecture")) {
2127                 *type = REG_SZ;
2128                 data->string = talloc_strdup(mem_ctx,
2129                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2130                 W_ERROR_HAVE_NO_MEMORY(data->string);
2131
2132                 return WERR_OK;
2133         }
2134
2135         if (!StrCaseCmp(value, "DsPresent")) {
2136                 *type = REG_DWORD;
2137
2138                 /* only show the publish check box if we are a
2139                    member of a AD domain */
2140
2141                 if (lp_security() == SEC_ADS) {
2142                         data->value = 0x01;
2143                 } else {
2144                         data->value = 0x00;
2145                 }
2146                 return WERR_OK;
2147         }
2148
2149         if (!StrCaseCmp(value, "DNSMachineName")) {
2150                 const char *hostname = get_mydnsfullname();
2151
2152                 if (!hostname) {
2153                         return WERR_BADFILE;
2154                 }
2155
2156                 *type = REG_SZ;
2157                 data->string = talloc_strdup(mem_ctx, hostname);
2158                 W_ERROR_HAVE_NO_MEMORY(data->string);
2159
2160                 return WERR_OK;
2161         }
2162
2163         *type = REG_NONE;
2164
2165         return WERR_INVALID_PARAM;
2166 }
2167
2168 /****************************************************************
2169  _spoolss_GetPrinterData
2170 ****************************************************************/
2171
2172 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2173                                struct spoolss_GetPrinterData *r)
2174 {
2175         struct spoolss_GetPrinterDataEx r2;
2176
2177         r2.in.handle            = r->in.handle;
2178         r2.in.key_name          = "PrinterDriverData";
2179         r2.in.value_name        = r->in.value_name;
2180         r2.in.offered           = r->in.offered;
2181         r2.out.type             = r->out.type;
2182         r2.out.data             = r->out.data;
2183         r2.out.needed           = r->out.needed;
2184
2185         return _spoolss_GetPrinterDataEx(p, &r2);
2186 }
2187
2188 /*********************************************************
2189  Connect to the client machine.
2190 **********************************************************/
2191
2192 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2193                         struct sockaddr_storage *client_ss, const char *remote_machine)
2194 {
2195         NTSTATUS ret;
2196         struct cli_state *the_cli;
2197         struct sockaddr_storage rm_addr;
2198         char addr[INET6_ADDRSTRLEN];
2199
2200         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2201                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2202                         remote_machine));
2203                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2204                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2205                         return false;
2206                 }
2207                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2208         } else {
2209                 rm_addr = *client_ss;
2210                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2211                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2212                         addr));
2213         }
2214
2215         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2216                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2217                         addr));
2218                 return false;
2219         }
2220
2221         /* setup the connection */
2222         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2223                 &rm_addr, 0, "IPC$", "IPC",
2224                 "", /* username */
2225                 "", /* domain */
2226                 "", /* password */
2227                 0, lp_client_signing(), NULL );
2228
2229         if ( !NT_STATUS_IS_OK( ret ) ) {
2230                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2231                         remote_machine ));
2232                 return false;
2233         }
2234
2235         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2236                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2237                 cli_shutdown(the_cli);
2238                 return false;
2239         }
2240
2241         /*
2242          * Ok - we have an anonymous connection to the IPC$ share.
2243          * Now start the NT Domain stuff :-).
2244          */
2245
2246         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2247         if (!NT_STATUS_IS_OK(ret)) {
2248                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2249                         remote_machine, nt_errstr(ret)));
2250                 cli_shutdown(the_cli);
2251                 return false;
2252         }
2253
2254         return true;
2255 }
2256
2257 /***************************************************************************
2258  Connect to the client.
2259 ****************************************************************************/
2260
2261 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2262                                         uint32_t localprinter, uint32_t type,
2263                                         struct policy_handle *handle,
2264                                         struct sockaddr_storage *client_ss)
2265 {
2266         WERROR result;
2267         NTSTATUS status;
2268
2269         /*
2270          * If it's the first connection, contact the client
2271          * and connect to the IPC$ share anonymously
2272          */
2273         if (smb_connections==0) {
2274                 fstring unix_printer;
2275
2276                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2277
2278                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2279                         return false;
2280
2281                 messaging_register(smbd_messaging_context(), NULL,
2282                                    MSG_PRINTER_NOTIFY2,
2283                                    receive_notify2_message_list);
2284                 /* Tell the connections db we're now interested in printer
2285                  * notify messages. */
2286                 serverid_register_msg_flags(
2287                         messaging_server_id(smbd_messaging_context()),
2288                         true, FLAG_MSG_PRINT_NOTIFY);
2289         }
2290
2291         /*
2292          * Tell the specific printing tdb we want messages for this printer
2293          * by registering our PID.
2294          */
2295
2296         if (!print_notify_register_pid(snum))
2297                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2298
2299         smb_connections++;
2300
2301         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2302                                                  printer,
2303                                                  localprinter,
2304                                                  type,
2305                                                  0,
2306                                                  NULL,
2307                                                  handle,
2308                                                  &result);
2309         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2310                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2311                         win_errstr(result)));
2312
2313         return (W_ERROR_IS_OK(result));
2314 }
2315
2316 /****************************************************************
2317  ****************************************************************/
2318
2319 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2320                                                              const struct spoolss_NotifyOption *r)
2321 {
2322         struct spoolss_NotifyOption *option;
2323         uint32_t i,k;
2324
2325         if (!r) {
2326                 return NULL;
2327         }
2328
2329         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2330         if (!option) {
2331                 return NULL;
2332         }
2333
2334         *option = *r;
2335
2336         if (!option->count) {
2337                 return option;
2338         }
2339
2340         option->types = talloc_zero_array(option,
2341                 struct spoolss_NotifyOptionType, option->count);
2342         if (!option->types) {
2343                 talloc_free(option);
2344                 return NULL;
2345         }
2346
2347         for (i=0; i < option->count; i++) {
2348                 option->types[i] = r->types[i];
2349
2350                 if (option->types[i].count) {
2351                         option->types[i].fields = talloc_zero_array(option,
2352                                 union spoolss_Field, option->types[i].count);
2353                         if (!option->types[i].fields) {
2354                                 talloc_free(option);
2355                                 return NULL;
2356                         }
2357                         for (k=0; k<option->types[i].count; k++) {
2358                                 option->types[i].fields[k] =
2359                                         r->types[i].fields[k];
2360                         }
2361                 }
2362         }
2363
2364         return option;
2365 }
2366
2367 /****************************************************************
2368  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2369  *
2370  * before replying OK: status=0 a rpc call is made to the workstation
2371  * asking ReplyOpenPrinter
2372  *
2373  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2374  * called from api_spoolss_rffpcnex
2375 ****************************************************************/
2376
2377 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2378                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2379 {
2380         int snum = -1;
2381         struct spoolss_NotifyOption *option = r->in.notify_options;
2382         struct sockaddr_storage client_ss;
2383
2384         /* store the notify value in the printer struct */
2385
2386         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2387
2388         if (!Printer) {
2389                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2390                         "Invalid handle (%s:%u:%u).\n",
2391                         OUR_HANDLE(r->in.handle)));
2392                 return WERR_BADFID;
2393         }
2394
2395         Printer->notify.flags           = r->in.flags;
2396         Printer->notify.options         = r->in.options;
2397         Printer->notify.printerlocal    = r->in.printer_local;
2398
2399         TALLOC_FREE(Printer->notify.option);
2400         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2401
2402         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2403
2404         /* Connect to the client machine and send a ReplyOpenPrinter */
2405
2406         if ( Printer->printer_type == SPLHND_SERVER)
2407                 snum = -1;
2408         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2409                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2410                 return WERR_BADFID;
2411
2412         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2413                 "client_address is %s\n", p->client_address));
2414
2415         if (!interpret_string_addr(&client_ss, p->client_address,
2416                                    AI_NUMERICHOST)) {
2417                 return WERR_SERVER_UNAVAILABLE;
2418         }
2419
2420         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2421                                         Printer->notify.printerlocal, 1,
2422                                         &Printer->notify.client_hnd, &client_ss))
2423                 return WERR_SERVER_UNAVAILABLE;
2424
2425         Printer->notify.client_connected = true;
2426
2427         return WERR_OK;
2428 }
2429
2430 /*******************************************************************
2431  * fill a notify_info_data with the servername
2432  ********************************************************************/
2433
2434 static void spoolss_notify_server_name(int snum,
2435                                        struct spoolss_Notify *data,
2436                                        print_queue_struct *queue,
2437                                        struct spoolss_PrinterInfo2 *pinfo2,
2438                                        TALLOC_CTX *mem_ctx)
2439 {
2440         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2441 }
2442
2443 /*******************************************************************
2444  * fill a notify_info_data with the printername (not including the servername).
2445  ********************************************************************/
2446
2447 static void spoolss_notify_printer_name(int snum,
2448                                         struct spoolss_Notify *data,
2449                                         print_queue_struct *queue,
2450                                         struct spoolss_PrinterInfo2 *pinfo2,
2451                                         TALLOC_CTX *mem_ctx)
2452 {
2453         /* the notify name should not contain the \\server\ part */
2454         const char *p = strrchr(pinfo2->printername, '\\');
2455
2456         if (!p) {
2457                 p = pinfo2->printername;
2458         } else {
2459                 p++;
2460         }
2461
2462         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2463 }
2464
2465 /*******************************************************************
2466  * fill a notify_info_data with the servicename
2467  ********************************************************************/
2468
2469 static void spoolss_notify_share_name(int snum,
2470                                       struct spoolss_Notify *data,
2471                                       print_queue_struct *queue,
2472                                       struct spoolss_PrinterInfo2 *pinfo2,
2473                                       TALLOC_CTX *mem_ctx)
2474 {
2475         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2476 }
2477
2478 /*******************************************************************
2479  * fill a notify_info_data with the port name
2480  ********************************************************************/
2481
2482 static void spoolss_notify_port_name(int snum,
2483                                      struct spoolss_Notify *data,
2484                                      print_queue_struct *queue,
2485                                      struct spoolss_PrinterInfo2 *pinfo2,
2486                                      TALLOC_CTX *mem_ctx)
2487 {
2488         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2489 }
2490
2491 /*******************************************************************
2492  * fill a notify_info_data with the printername
2493  * but it doesn't exist, have to see what to do
2494  ********************************************************************/
2495
2496 static void spoolss_notify_driver_name(int snum,
2497                                        struct spoolss_Notify *data,
2498                                        print_queue_struct *queue,
2499                                        struct spoolss_PrinterInfo2 *pinfo2,
2500                                        TALLOC_CTX *mem_ctx)
2501 {
2502         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2503 }
2504
2505 /*******************************************************************
2506  * fill a notify_info_data with the comment
2507  ********************************************************************/
2508
2509 static void spoolss_notify_comment(int snum,
2510                                    struct spoolss_Notify *data,
2511                                    print_queue_struct *queue,
2512                                    struct spoolss_PrinterInfo2 *pinfo2,
2513                                    TALLOC_CTX *mem_ctx)
2514 {
2515         const char *p;
2516
2517         if (*pinfo2->comment == '\0') {
2518                 p = lp_comment(snum);
2519         } else {
2520                 p = pinfo2->comment;
2521         }
2522
2523         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2524 }
2525
2526 /*******************************************************************
2527  * fill a notify_info_data with the comment
2528  * location = "Room 1, floor 2, building 3"
2529  ********************************************************************/
2530
2531 static void spoolss_notify_location(int snum,
2532                                     struct spoolss_Notify *data,
2533                                     print_queue_struct *queue,
2534                                     struct spoolss_PrinterInfo2 *pinfo2,
2535                                     TALLOC_CTX *mem_ctx)
2536 {
2537         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2538 }
2539
2540 /*******************************************************************
2541  * fill a notify_info_data with the device mode
2542  * jfm:xxxx don't to it for know but that's a real problem !!!
2543  ********************************************************************/
2544
2545 static void spoolss_notify_devmode(int snum,
2546                                    struct spoolss_Notify *data,
2547                                    print_queue_struct *queue,
2548                                    struct spoolss_PrinterInfo2 *pinfo2,
2549                                    TALLOC_CTX *mem_ctx)
2550 {
2551         /* for a dummy implementation we have to zero the fields */
2552         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2553 }
2554
2555 /*******************************************************************
2556  * fill a notify_info_data with the separator file name
2557  ********************************************************************/
2558
2559 static void spoolss_notify_sepfile(int snum,
2560                                    struct spoolss_Notify *data,
2561                                    print_queue_struct *queue,
2562                                    struct spoolss_PrinterInfo2 *pinfo2,
2563                                    TALLOC_CTX *mem_ctx)
2564 {
2565         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2566 }
2567
2568 /*******************************************************************
2569  * fill a notify_info_data with the print processor
2570  * jfm:xxxx return always winprint to indicate we don't do anything to it
2571  ********************************************************************/
2572
2573 static void spoolss_notify_print_processor(int snum,
2574                                            struct spoolss_Notify *data,
2575                                            print_queue_struct *queue,
2576                                            struct spoolss_PrinterInfo2 *pinfo2,
2577                                            TALLOC_CTX *mem_ctx)
2578 {
2579         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2580 }
2581
2582 /*******************************************************************
2583  * fill a notify_info_data with the print processor options
2584  * jfm:xxxx send an empty string
2585  ********************************************************************/
2586
2587 static void spoolss_notify_parameters(int snum,
2588                                       struct spoolss_Notify *data,
2589                                       print_queue_struct *queue,
2590                                       struct spoolss_PrinterInfo2 *pinfo2,
2591                                       TALLOC_CTX *mem_ctx)
2592 {
2593         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2594 }
2595
2596 /*******************************************************************
2597  * fill a notify_info_data with the data type
2598  * jfm:xxxx always send RAW as data type
2599  ********************************************************************/
2600
2601 static void spoolss_notify_datatype(int snum,
2602                                     struct spoolss_Notify *data,
2603                                     print_queue_struct *queue,
2604                                     struct spoolss_PrinterInfo2 *pinfo2,
2605                                     TALLOC_CTX *mem_ctx)
2606 {
2607         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2608 }
2609
2610 /*******************************************************************
2611  * fill a notify_info_data with the security descriptor
2612  * jfm:xxxx send an null pointer to say no security desc
2613  * have to implement security before !
2614  ********************************************************************/
2615
2616 static void spoolss_notify_security_desc(int snum,
2617                                          struct spoolss_Notify *data,
2618                                          print_queue_struct *queue,
2619                                          struct spoolss_PrinterInfo2 *pinfo2,
2620                                          TALLOC_CTX *mem_ctx)
2621 {
2622         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2623 }
2624
2625 /*******************************************************************
2626  * fill a notify_info_data with the attributes
2627  * jfm:xxxx a samba printer is always shared
2628  ********************************************************************/
2629
2630 static void spoolss_notify_attributes(int snum,
2631                                       struct spoolss_Notify *data,
2632                                       print_queue_struct *queue,
2633                                       struct spoolss_PrinterInfo2 *pinfo2,
2634                                       TALLOC_CTX *mem_ctx)
2635 {
2636         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2637 }
2638
2639 /*******************************************************************
2640  * fill a notify_info_data with the priority
2641  ********************************************************************/
2642
2643 static void spoolss_notify_priority(int snum,
2644                                     struct spoolss_Notify *data,
2645                                     print_queue_struct *queue,
2646                                     struct spoolss_PrinterInfo2 *pinfo2,
2647                                     TALLOC_CTX *mem_ctx)
2648 {
2649         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2650 }
2651
2652 /*******************************************************************
2653  * fill a notify_info_data with the default priority
2654  ********************************************************************/
2655
2656 static void spoolss_notify_default_priority(int snum,
2657                                             struct spoolss_Notify *data,
2658                                             print_queue_struct *queue,
2659                                             struct spoolss_PrinterInfo2 *pinfo2,
2660                                             TALLOC_CTX *mem_ctx)
2661 {
2662         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2663 }
2664
2665 /*******************************************************************
2666  * fill a notify_info_data with the start time
2667  ********************************************************************/
2668
2669 static void spoolss_notify_start_time(int snum,
2670                                       struct spoolss_Notify *data,
2671                                       print_queue_struct *queue,
2672                                       struct spoolss_PrinterInfo2 *pinfo2,
2673                                       TALLOC_CTX *mem_ctx)
2674 {
2675         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2676 }
2677
2678 /*******************************************************************
2679  * fill a notify_info_data with the until time
2680  ********************************************************************/
2681
2682 static void spoolss_notify_until_time(int snum,
2683                                       struct spoolss_Notify *data,
2684                                       print_queue_struct *queue,
2685                                       struct spoolss_PrinterInfo2 *pinfo2,
2686                                       TALLOC_CTX *mem_ctx)
2687 {
2688         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2689 }
2690
2691 /*******************************************************************
2692  * fill a notify_info_data with the status
2693  ********************************************************************/
2694
2695 static void spoolss_notify_status(int snum,
2696                                   struct spoolss_Notify *data,
2697                                   print_queue_struct *queue,
2698                                   struct spoolss_PrinterInfo2 *pinfo2,
2699                                   TALLOC_CTX *mem_ctx)
2700 {
2701         print_status_struct status;
2702
2703         print_queue_length(snum, &status);
2704         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2705 }
2706
2707 /*******************************************************************
2708  * fill a notify_info_data with the number of jobs queued
2709  ********************************************************************/
2710
2711 static void spoolss_notify_cjobs(int snum,
2712                                  struct spoolss_Notify *data,
2713                                  print_queue_struct *queue,
2714                                  struct spoolss_PrinterInfo2 *pinfo2,
2715                                  TALLOC_CTX *mem_ctx)
2716 {
2717         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2718 }
2719
2720 /*******************************************************************
2721  * fill a notify_info_data with the average ppm
2722  ********************************************************************/
2723
2724 static void spoolss_notify_average_ppm(int snum,
2725                                        struct spoolss_Notify *data,
2726                                        print_queue_struct *queue,
2727                                        struct spoolss_PrinterInfo2 *pinfo2,
2728                                        TALLOC_CTX *mem_ctx)
2729 {
2730         /* always respond 8 pages per minutes */
2731         /* a little hard ! */
2732         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2733 }
2734
2735 /*******************************************************************
2736  * fill a notify_info_data with username
2737  ********************************************************************/
2738
2739 static void spoolss_notify_username(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, queue->fs_user);
2746 }
2747
2748 /*******************************************************************
2749  * fill a notify_info_data with job status
2750  ********************************************************************/
2751
2752 static void spoolss_notify_job_status(int snum,
2753                                       struct spoolss_Notify *data,
2754                                       print_queue_struct *queue,
2755                                       struct spoolss_PrinterInfo2 *pinfo2,
2756                                       TALLOC_CTX *mem_ctx)
2757 {
2758         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2759 }
2760
2761 /*******************************************************************
2762  * fill a notify_info_data with job name
2763  ********************************************************************/
2764
2765 static void spoolss_notify_job_name(int snum,
2766                                     struct spoolss_Notify *data,
2767                                     print_queue_struct *queue,
2768                                     struct spoolss_PrinterInfo2 *pinfo2,
2769                                     TALLOC_CTX *mem_ctx)
2770 {
2771         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2772 }
2773
2774 /*******************************************************************
2775  * fill a notify_info_data with job status
2776  ********************************************************************/
2777
2778 static void spoolss_notify_job_status_string(int snum,
2779                                              struct spoolss_Notify *data,
2780                                              print_queue_struct *queue,
2781                                              struct spoolss_PrinterInfo2 *pinfo2,
2782                                              TALLOC_CTX *mem_ctx)
2783 {
2784         /*
2785          * Now we're returning job status codes we just return a "" here. JRA.
2786          */
2787
2788         const char *p = "";
2789
2790 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2791         p = "unknown";
2792
2793         switch (queue->status) {
2794         case LPQ_QUEUED:
2795                 p = "Queued";
2796                 break;
2797         case LPQ_PAUSED:
2798                 p = "";    /* NT provides the paused string */
2799                 break;
2800         case LPQ_SPOOLING:
2801                 p = "Spooling";
2802                 break;
2803         case LPQ_PRINTING:
2804                 p = "Printing";
2805                 break;
2806         }
2807 #endif /* NO LONGER NEEDED. */
2808
2809         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2810 }
2811
2812 /*******************************************************************
2813  * fill a notify_info_data with job time
2814  ********************************************************************/
2815
2816 static void spoolss_notify_job_time(int snum,
2817                                     struct spoolss_Notify *data,
2818                                     print_queue_struct *queue,
2819                                     struct spoolss_PrinterInfo2 *pinfo2,
2820                                     TALLOC_CTX *mem_ctx)
2821 {
2822         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2823 }
2824
2825 /*******************************************************************
2826  * fill a notify_info_data with job size
2827  ********************************************************************/
2828
2829 static void spoolss_notify_job_size(int snum,
2830                                     struct spoolss_Notify *data,
2831                                     print_queue_struct *queue,
2832                                     struct spoolss_PrinterInfo2 *pinfo2,
2833                                     TALLOC_CTX *mem_ctx)
2834 {
2835         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2836 }
2837
2838 /*******************************************************************
2839  * fill a notify_info_data with page info
2840  ********************************************************************/
2841 static void spoolss_notify_total_pages(int snum,
2842                                 struct spoolss_Notify *data,
2843                                 print_queue_struct *queue,
2844                                 struct spoolss_PrinterInfo2 *pinfo2,
2845                                 TALLOC_CTX *mem_ctx)
2846 {
2847         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2848 }
2849
2850 /*******************************************************************
2851  * fill a notify_info_data with pages printed info.
2852  ********************************************************************/
2853 static void spoolss_notify_pages_printed(int snum,
2854                                 struct spoolss_Notify *data,
2855                                 print_queue_struct *queue,
2856                                 struct spoolss_PrinterInfo2 *pinfo2,
2857                                 TALLOC_CTX *mem_ctx)
2858 {
2859         /* Add code when back-end tracks this */
2860         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2861 }
2862
2863 /*******************************************************************
2864  Fill a notify_info_data with job position.
2865  ********************************************************************/
2866
2867 static void spoolss_notify_job_position(int snum,
2868                                         struct spoolss_Notify *data,
2869                                         print_queue_struct *queue,
2870                                         struct spoolss_PrinterInfo2 *pinfo2,
2871                                         TALLOC_CTX *mem_ctx)
2872 {
2873         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2874 }
2875
2876 /*******************************************************************
2877  Fill a notify_info_data with submitted time.
2878  ********************************************************************/
2879
2880 static void spoolss_notify_submitted_time(int snum,
2881                                           struct spoolss_Notify *data,
2882                                           print_queue_struct *queue,
2883                                           struct spoolss_PrinterInfo2 *pinfo2,
2884                                           TALLOC_CTX *mem_ctx)
2885 {
2886         data->data.string.string = NULL;
2887         data->data.string.size = 0;
2888
2889         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2890                                &data->data.string.string,
2891                                &data->data.string.size);
2892
2893 }
2894
2895 struct s_notify_info_data_table
2896 {
2897         enum spoolss_NotifyType type;
2898         uint16_t field;
2899         const char *name;
2900         enum spoolss_NotifyTable variable_type;
2901         void (*fn) (int snum, struct spoolss_Notify *data,
2902                     print_queue_struct *queue,
2903                     struct spoolss_PrinterInfo2 *pinfo2,
2904                     TALLOC_CTX *mem_ctx);
2905 };
2906
2907 /* A table describing the various print notification constants and
2908    whether the notification data is a pointer to a variable sized
2909    buffer, a one value uint32_t or a two value uint32_t. */
2910
2911 static const struct s_notify_info_data_table notify_info_data_table[] =
2912 {
2913 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2914 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2915 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
2916 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2917 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2918 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
2919 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
2920 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2921 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
2922 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2923 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2924 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2925 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
2926 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
2927 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2928 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
2929 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2930 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2931 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
2932 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
2933 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
2934 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
2935 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
2936 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2937 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
2938 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2939 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2940 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2941 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2942 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
2943 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
2944 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2945 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2946 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2947 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2948 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2949 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
2950 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
2951 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
2952 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
2953 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2954 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
2955 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
2956 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2957 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2958 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
2959 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
2960 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
2961 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
2962 };
2963
2964 /*******************************************************************
2965  Return the variable_type of info_data structure.
2966 ********************************************************************/
2967
2968 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2969                                                   uint16_t field)
2970 {
2971         int i=0;
2972
2973         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2974                 if ( (notify_info_data_table[i].type == type) &&
2975                      (notify_info_data_table[i].field == field) ) {
2976                         return notify_info_data_table[i].variable_type;
2977                 }
2978         }
2979
2980         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2981
2982         return 0;
2983 }
2984
2985 /****************************************************************************
2986 ****************************************************************************/
2987
2988 static bool search_notify(enum spoolss_NotifyType type,
2989                           uint16_t field,
2990                           int *value)
2991 {
2992         int i;
2993
2994         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2995                 if (notify_info_data_table[i].type == type &&
2996                     notify_info_data_table[i].field == field &&
2997                     notify_info_data_table[i].fn != NULL) {
2998                         *value = i;
2999                         return true;
3000                 }
3001         }
3002
3003         return false;
3004 }
3005
3006 /****************************************************************************
3007 ****************************************************************************/
3008
3009 static void construct_info_data(struct spoolss_Notify *info_data,
3010                                 enum spoolss_NotifyType type,
3011                                 uint16_t field, int id)
3012 {
3013         info_data->type                 = type;
3014         info_data->field.field          = field;
3015         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3016         info_data->job_id               = id;
3017 }
3018
3019 /*******************************************************************
3020  *
3021  * fill a notify_info struct with info asked
3022  *
3023  ********************************************************************/
3024
3025 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3026                                           struct spoolss_NotifyInfo *info,
3027                                           struct spoolss_PrinterInfo2 *pinfo2,
3028                                           int snum,
3029                                           const struct spoolss_NotifyOptionType *option_type,
3030                                           uint32_t id,
3031                                           TALLOC_CTX *mem_ctx)
3032 {
3033         int field_num,j;
3034         enum spoolss_NotifyType type;
3035         uint16_t field;
3036
3037         struct spoolss_Notify *current_data;
3038         print_queue_struct *queue=NULL;
3039
3040         type = option_type->type;
3041
3042         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3043                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3044                 option_type->count, lp_servicename(snum)));
3045
3046         for(field_num=0; field_num < option_type->count; field_num++) {
3047                 field = option_type->fields[field_num].field;
3048
3049                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3050
3051                 if (!search_notify(type, field, &j) )
3052                         continue;
3053
3054                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3055                                                       struct spoolss_Notify,
3056                                                       info->count + 1);
3057                 if (info->notifies == NULL) {
3058                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3059                         return false;
3060                 }
3061
3062                 current_data = &info->notifies[info->count];
3063
3064                 construct_info_data(current_data, type, field, id);
3065
3066                 DEBUG(10, ("construct_notify_printer_info: "
3067                            "calling [%s]  snum=%d  printername=[%s])\n",
3068                            notify_info_data_table[j].name, snum,
3069                            pinfo2->printername));
3070
3071                 notify_info_data_table[j].fn(snum, current_data, queue,
3072                                              pinfo2, mem_ctx);
3073
3074                 info->count++;
3075         }
3076
3077         return true;
3078 }
3079
3080 /*******************************************************************
3081  *
3082  * fill a notify_info struct with info asked
3083  *
3084  ********************************************************************/
3085
3086 static bool construct_notify_jobs_info(print_queue_struct *queue,
3087                                        struct spoolss_NotifyInfo *info,
3088                                        struct spoolss_PrinterInfo2 *pinfo2,
3089                                        int snum,
3090                                        const struct spoolss_NotifyOptionType *option_type,
3091                                        uint32_t id,
3092                                        TALLOC_CTX *mem_ctx)
3093 {
3094         int field_num,j;
3095         enum spoolss_NotifyType type;
3096         uint16_t field;
3097         struct spoolss_Notify *current_data;
3098
3099         DEBUG(4,("construct_notify_jobs_info\n"));
3100
3101         type = option_type->type;
3102
3103         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3104                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3105                 option_type->count));
3106
3107         for(field_num=0; field_num<option_type->count; field_num++) {
3108                 field = option_type->fields[field_num].field;
3109
3110                 if (!search_notify(type, field, &j) )
3111                         continue;
3112
3113                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3114                                                       struct spoolss_Notify,
3115                                                       info->count + 1);
3116                 if (info->notifies == NULL) {
3117                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3118                         return false;
3119                 }
3120
3121                 current_data=&(info->notifies[info->count]);
3122
3123                 construct_info_data(current_data, type, field, id);
3124                 notify_info_data_table[j].fn(snum, current_data, queue,
3125                                              pinfo2, mem_ctx);
3126                 info->count++;
3127         }
3128
3129         return true;
3130 }
3131
3132 /*
3133  * JFM: The enumeration is not that simple, it's even non obvious.
3134  *
3135  * let's take an example: I want to monitor the PRINTER SERVER for
3136  * the printer's name and the number of jobs currently queued.
3137  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3138  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3139  *
3140  * I have 3 printers on the back of my server.
3141  *
3142  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3143  * structures.
3144  *   Number     Data                    Id
3145  *      1       printer 1 name          1
3146  *      2       printer 1 cjob          1
3147  *      3       printer 2 name          2
3148  *      4       printer 2 cjob          2
3149  *      5       printer 3 name          3
3150  *      6       printer 3 name          3
3151  *
3152  * that's the print server case, the printer case is even worse.
3153  */
3154
3155 /*******************************************************************
3156  *
3157  * enumerate all printers on the printserver
3158  * fill a notify_info struct with info asked
3159  *
3160  ********************************************************************/
3161
3162 static WERROR printserver_notify_info(pipes_struct *p,
3163                                       struct policy_handle *hnd,
3164                                       struct spoolss_NotifyInfo *info,
3165                                       TALLOC_CTX *mem_ctx)
3166 {
3167         int snum;
3168         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3169         int n_services=lp_numservices();
3170         int i;
3171         struct spoolss_NotifyOption *option;
3172         struct spoolss_NotifyOptionType option_type;
3173         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3174         WERROR result;
3175
3176         DEBUG(4,("printserver_notify_info\n"));
3177
3178         if (!Printer)
3179                 return WERR_BADFID;
3180
3181         option = Printer->notify.option;
3182
3183         info->version   = 2;
3184         info->notifies  = NULL;
3185         info->count     = 0;
3186
3187         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3188            sending a ffpcn() request first */
3189
3190         if ( !option )
3191                 return WERR_BADFID;
3192
3193         for (i=0; i<option->count; i++) {
3194                 option_type = option->types[i];
3195
3196                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3197                         continue;
3198
3199                 for (snum = 0; snum < n_services; snum++) {
3200                         if (!lp_browseable(snum) ||
3201                             !lp_snum_ok(snum) ||
3202                             !lp_print_ok(snum)) {
3203                                 continue; /* skip */
3204                         }
3205
3206                         /* FIXME: should we use a SYSTEM server_info here? */
3207                         result = winreg_get_printer(mem_ctx, p->server_info,
3208                                                     Printer->servername,
3209                                                     lp_servicename(snum),
3210                                                     &pinfo2);
3211                         if (!W_ERROR_IS_OK(result)) {
3212                                 DEBUG(4, ("printserver_notify_info: "
3213                                           "Failed to get printer [%s]\n",
3214                                           lp_servicename(snum)));
3215                                 continue;
3216                         }
3217
3218
3219                         construct_notify_printer_info(Printer, info,
3220                                                       pinfo2, snum,
3221                                                       &option_type, snum,
3222                                                       mem_ctx);
3223
3224                         TALLOC_FREE(pinfo2);
3225                 }
3226         }
3227
3228 #if 0
3229         /*
3230          * Debugging information, don't delete.
3231          */
3232
3233         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3234         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3235         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3236
3237         for (i=0; i<info->count; i++) {
3238                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3239                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3240                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3241         }
3242 #endif
3243
3244         return WERR_OK;
3245 }
3246
3247 /*******************************************************************
3248  *
3249  * fill a notify_info struct with info asked
3250  *
3251  ********************************************************************/
3252
3253 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3254                                   struct spoolss_NotifyInfo *info,
3255                                   TALLOC_CTX *mem_ctx)
3256 {
3257         int snum;
3258         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3259         int i;
3260         uint32_t id;
3261         struct spoolss_NotifyOption *option;
3262         struct spoolss_NotifyOptionType option_type;
3263         int count,j;
3264         print_queue_struct *queue=NULL;
3265         print_status_struct status;
3266         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3267         WERROR result;
3268
3269         DEBUG(4,("printer_notify_info\n"));
3270
3271         if (!Printer)
3272                 return WERR_BADFID;
3273
3274         option = Printer->notify.option;
3275         id = 0x0;
3276
3277         info->version   = 2;
3278         info->notifies  = NULL;
3279         info->count     = 0;
3280
3281         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3282            sending a ffpcn() request first */
3283
3284         if ( !option )
3285                 return WERR_BADFID;
3286
3287         get_printer_snum(p, hnd, &snum, NULL);
3288
3289         /* FIXME: should we use a SYSTEM server_info here ? */
3290         result = winreg_get_printer(mem_ctx, p->server_info,
3291                                     Printer->servername,
3292                                     lp_servicename(snum), &pinfo2);
3293         if (!W_ERROR_IS_OK(result)) {
3294                 return WERR_BADFID;
3295         }
3296
3297         for (i=0; i<option->count; i++) {
3298                 option_type = option->types[i];
3299
3300                 switch (option_type.type) {
3301                 case PRINTER_NOTIFY_TYPE:
3302                         if (construct_notify_printer_info(Printer, info,
3303                                                           pinfo2, snum,
3304                                                           &option_type, id,
3305                                                           mem_ctx)) {
3306                                 id--;
3307                         }
3308                         break;
3309
3310                 case JOB_NOTIFY_TYPE:
3311
3312                         count = print_queue_status(snum, &queue, &status);
3313
3314                         for (j=0; j<count; j++) {
3315                                 construct_notify_jobs_info(&queue[j], info,
3316                                                            pinfo2, snum,
3317                                                            &option_type,
3318                                                            queue[j].job,
3319                                                            mem_ctx);
3320                         }
3321
3322                         SAFE_FREE(queue);
3323                         break;
3324                 }
3325         }
3326
3327         /*
3328          * Debugging information, don't delete.
3329          */
3330         /*
3331         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3332         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3333         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3334
3335         for (i=0; i<info->count; i++) {
3336                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3337                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3338                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3339         }
3340         */
3341
3342         talloc_free(pinfo2);
3343         return WERR_OK;
3344 }
3345
3346 /****************************************************************
3347  _spoolss_RouterRefreshPrinterChangeNotify
3348 ****************************************************************/
3349
3350 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3351                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3352 {
3353         struct spoolss_NotifyInfo *info;
3354
3355         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3356         WERROR result = WERR_BADFID;
3357
3358         /* we always have a spoolss_NotifyInfo struct */
3359         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3360         if (!info) {
3361                 result = WERR_NOMEM;
3362                 goto done;
3363         }
3364
3365         *r->out.info = info;
3366
3367         if (!Printer) {
3368                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3369                         "Invalid handle (%s:%u:%u).\n",
3370                         OUR_HANDLE(r->in.handle)));
3371                 goto done;
3372         }
3373
3374         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3375
3376         /*
3377          *      We are now using the change value, and
3378          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3379          *      I don't have a global notification system, I'm sending back all the
3380          *      informations even when _NOTHING_ has changed.
3381          */
3382
3383         /* We need to keep track of the change value to send back in
3384            RRPCN replies otherwise our updates are ignored. */
3385
3386         Printer->notify.fnpcn = true;
3387
3388         if (Printer->notify.client_connected) {
3389                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3390                         "Saving change value in request [%x]\n",
3391                         r->in.change_low));
3392                 Printer->notify.change = r->in.change_low;
3393         }
3394
3395         /* just ignore the spoolss_NotifyOption */
3396
3397         switch (Printer->printer_type) {
3398                 case SPLHND_SERVER:
3399                         result = printserver_notify_info(p, r->in.handle,
3400                                                          info, p->mem_ctx);
3401                         break;
3402
3403                 case SPLHND_PRINTER:
3404                         result = printer_notify_info(p, r->in.handle,
3405                                                      info, p->mem_ctx);
3406                         break;
3407         }
3408
3409         Printer->notify.fnpcn = false;
3410
3411 done:
3412         return result;
3413 }
3414
3415 /********************************************************************
3416  * construct_printer_info_0
3417  * fill a printer_info_0 struct
3418  ********************************************************************/
3419
3420 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3421                                       struct auth_serversupplied_info *server_info,
3422                                       struct spoolss_PrinterInfo2 *info2,
3423                                       struct spoolss_PrinterInfo0 *r,
3424                                       int snum)
3425 {
3426         int count;
3427         counter_printer_0 *session_counter;
3428         struct timeval setuptime;
3429         print_status_struct status;
3430
3431         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3432         W_ERROR_HAVE_NO_MEMORY(r->printername);
3433
3434         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3435         W_ERROR_HAVE_NO_MEMORY(r->servername);
3436
3437         count = print_queue_length(snum, &status);
3438
3439         /* check if we already have a counter for this printer */
3440         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3441                 if (session_counter->snum == snum)
3442                         break;
3443         }
3444
3445         /* it's the first time, add it to the list */
3446         if (session_counter == NULL) {
3447                 session_counter = SMB_MALLOC_P(counter_printer_0);
3448                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3449                 ZERO_STRUCTP(session_counter);
3450                 session_counter->snum           = snum;
3451                 session_counter->counter        = 0;
3452                 DLIST_ADD(counter_list, session_counter);
3453         }
3454
3455         /* increment it */
3456         session_counter->counter++;
3457
3458         r->cjobs                        = count;
3459         r->total_jobs                   = 0;
3460         r->total_bytes                  = 0;
3461
3462         get_startup_time(&setuptime);
3463         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3464
3465         /* JFM:
3466          * the global_counter should be stored in a TDB as it's common to all the clients
3467          * and should be zeroed on samba startup
3468          */
3469         r->global_counter               = session_counter->counter;
3470         r->total_pages                  = 0;
3471         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3472         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3473         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3474         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3475         r->spooling                     = 0;
3476         r->max_spooling                 = 0;
3477         r->session_counter              = session_counter->counter;
3478         r->num_error_out_of_paper       = 0x0;
3479         r->num_error_not_ready          = 0x0;          /* number of print failure */
3480         r->job_error                    = 0x0;
3481         r->number_of_processors         = 0x1;
3482         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3483         r->high_part_total_bytes        = 0x0;
3484         winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3485         r->last_error                   = WERR_OK;
3486         r->status                       = nt_printq_status(status.status);
3487         r->enumerate_network_printers   = 0x0;
3488         r->c_setprinter                 = 0x0;
3489         r->processor_architecture       = 0x0;
3490         r->processor_level              = 0x6;          /* 6  ???*/
3491         r->ref_ic                       = 0;
3492         r->reserved2                    = 0;
3493         r->reserved3                    = 0;
3494
3495         return WERR_OK;
3496 }
3497
3498
3499 /********************************************************************
3500  * construct_printer_info1
3501  * fill a spoolss_PrinterInfo1 struct
3502 ********************************************************************/
3503
3504 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3505                                       const struct spoolss_PrinterInfo2 *info2,
3506                                       uint32_t flags,
3507                                       struct spoolss_PrinterInfo1 *r,
3508                                       int snum)
3509 {
3510         r->flags                = flags;
3511
3512         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3513                                                   info2->printername,
3514                                                   info2->drivername,
3515                                                   info2->location);
3516         W_ERROR_HAVE_NO_MEMORY(r->description);
3517
3518         if (info2->comment == NULL || info2->comment[0] == '\0') {
3519                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3520         } else {
3521                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3522         }
3523         W_ERROR_HAVE_NO_MEMORY(r->comment);
3524
3525         r->name                 = talloc_strdup(mem_ctx, info2->printername);
3526         W_ERROR_HAVE_NO_MEMORY(r->name);
3527
3528         return WERR_OK;
3529 }
3530
3531 /********************************************************************
3532  * construct_printer_info2
3533  * fill a spoolss_PrinterInfo2 struct
3534 ********************************************************************/
3535
3536 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3537                                       const struct spoolss_PrinterInfo2 *info2,
3538                                       struct spoolss_PrinterInfo2 *r,
3539                                       int snum)
3540 {
3541         int count;
3542         print_status_struct status;
3543
3544         count = print_queue_length(snum, &status);
3545
3546         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3547         W_ERROR_HAVE_NO_MEMORY(r->servername);
3548         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3549         W_ERROR_HAVE_NO_MEMORY(r->printername);
3550         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3551         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3552         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3553         W_ERROR_HAVE_NO_MEMORY(r->portname);
3554         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3555         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3556
3557         if (info2->comment[0] == '\0') {
3558                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3559         } else {
3560                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3561         }
3562         W_ERROR_HAVE_NO_MEMORY(r->comment);
3563
3564         r->location             = talloc_strdup(mem_ctx, info2->location);
3565         W_ERROR_HAVE_NO_MEMORY(r->location);
3566         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3567         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3568         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3569         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3570         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3571         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3572         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3573         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3574
3575         r->attributes           = info2->attributes;
3576
3577         r->priority             = info2->priority;
3578         r->defaultpriority      = info2->defaultpriority;
3579         r->starttime            = info2->starttime;
3580         r->untiltime            = info2->untiltime;
3581         r->status               = nt_printq_status(status.status);
3582         r->cjobs                = count;
3583         r->averageppm           = info2->averageppm;
3584
3585         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3586         if (!r->devmode) {
3587                 DEBUG(8,("Returning NULL Devicemode!\n"));
3588         }
3589
3590         r->secdesc = NULL;
3591
3592         if (info2->secdesc != NULL) {
3593                 /* don't use talloc_steal() here unless you do a deep steal of all
3594                    the SEC_DESC members */
3595
3596                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
3597         }
3598
3599         return WERR_OK;
3600 }
3601
3602 /********************************************************************
3603  * construct_printer_info3
3604  * fill a spoolss_PrinterInfo3 struct
3605  ********************************************************************/
3606
3607 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3608                                       const struct spoolss_PrinterInfo2 *info2,
3609                                       struct spoolss_PrinterInfo3 *r,
3610                                       int snum)
3611 {
3612         /* These are the components of the SD we are returning. */
3613
3614         if (info2->secdesc != NULL) {
3615                 /* don't use talloc_steal() here unless you do a deep steal of all
3616                    the SEC_DESC members */
3617
3618                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3619                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3620         }
3621
3622         return WERR_OK;
3623 }
3624
3625 /********************************************************************
3626  * construct_printer_info4
3627  * fill a spoolss_PrinterInfo4 struct
3628  ********************************************************************/
3629
3630 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3631                                       const struct spoolss_PrinterInfo2 *info2,
3632                                       struct spoolss_PrinterInfo4 *r,
3633                                       int snum)
3634 {
3635         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3636         W_ERROR_HAVE_NO_MEMORY(r->printername);
3637         r->servername   = talloc_strdup(mem_ctx, info2->servername);
3638         W_ERROR_HAVE_NO_MEMORY(r->servername);
3639
3640         r->attributes   = info2->attributes;
3641
3642         return WERR_OK;
3643 }
3644
3645 /********************************************************************
3646  * construct_printer_info5
3647  * fill a spoolss_PrinterInfo5 struct
3648  ********************************************************************/
3649
3650 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3651                                       const struct spoolss_PrinterInfo2 *info2,
3652                                       struct spoolss_PrinterInfo5 *r,
3653                                       int snum)
3654 {
3655         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3656         W_ERROR_HAVE_NO_MEMORY(r->printername);
3657         r->portname     = talloc_strdup(mem_ctx, info2->portname);
3658         W_ERROR_HAVE_NO_MEMORY(r->portname);
3659
3660         r->attributes   = info2->attributes;
3661
3662         /* these two are not used by NT+ according to MSDN */
3663         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3664         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3665
3666         return WERR_OK;
3667 }
3668
3669 /********************************************************************
3670  * construct_printer_info_6
3671  * fill a spoolss_PrinterInfo6 struct
3672  ********************************************************************/
3673
3674 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3675                                       const struct spoolss_PrinterInfo2 *info2,
3676                                       struct spoolss_PrinterInfo6 *r,
3677                                       int snum)
3678 {
3679         int count;
3680         print_status_struct status;
3681
3682         count = print_queue_length(snum, &status);
3683
3684         r->status = nt_printq_status(status.status);
3685
3686         return WERR_OK;
3687 }
3688
3689 /********************************************************************
3690  * construct_printer_info7
3691  * fill a spoolss_PrinterInfo7 struct
3692  ********************************************************************/
3693
3694 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3695                                       Printer_entry *print_hnd,
3696                                       struct spoolss_PrinterInfo7 *r,
3697                                       int snum)
3698 {
3699         struct auth_serversupplied_info *server_info;
3700         struct GUID guid;
3701         NTSTATUS status;
3702
3703         status = make_server_info_system(mem_ctx, &server_info);
3704         if (!NT_STATUS_IS_OK(status)) {
3705                 DEBUG(0, ("construct_printer_info7: "
3706                           "Could not create system server_info\n"));
3707                 return WERR_NOMEM;
3708         }
3709
3710         if (is_printer_published(mem_ctx, server_info, print_hnd->servername,
3711                                  lp_servicename(snum), &guid, NULL)) {
3712                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3713                 r->action = DSPRINT_PUBLISH;
3714         } else {
3715                 r->guid = talloc_strdup(mem_ctx, "");
3716                 r->action = DSPRINT_UNPUBLISH;
3717         }
3718         W_ERROR_HAVE_NO_MEMORY(r->guid);
3719
3720         TALLOC_FREE(server_info);
3721         return WERR_OK;
3722 }
3723
3724 /********************************************************************
3725  * construct_printer_info8
3726  * fill a spoolss_PrinterInfo8 struct
3727  ********************************************************************/
3728
3729 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3730                                       const struct spoolss_PrinterInfo2 *info2,
3731                                       struct spoolss_DeviceModeInfo *r,
3732                                       int snum)
3733 {
3734         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3735         if (!r->devmode) {
3736                 DEBUG(8,("Returning NULL Devicemode!\n"));
3737         }
3738
3739         return WERR_OK;
3740 }
3741
3742
3743 /********************************************************************
3744 ********************************************************************/
3745
3746 static bool snum_is_shared_printer(int snum)
3747 {
3748         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3749 }
3750
3751 /********************************************************************
3752  Spoolss_enumprinters.
3753 ********************************************************************/
3754
3755 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3756                                            struct auth_serversupplied_info *server_info,
3757                                            uint32_t level,
3758                                            uint32_t flags,
3759                                            union spoolss_PrinterInfo **info_p,
3760                                            uint32_t *count_p)
3761 {
3762         int snum;
3763         int n_services = lp_numservices();
3764         union spoolss_PrinterInfo *info = NULL;
3765         uint32_t count = 0;
3766         WERROR result = WERR_OK;
3767
3768         *count_p = 0;
3769         *info_p = NULL;
3770
3771         for (snum = 0; snum < n_services; snum++) {
3772
3773                 const char *printer;
3774                 struct spoolss_PrinterInfo2 *info2;
3775
3776                 if (!snum_is_shared_printer(snum)) {
3777                         continue;
3778                 }
3779
3780                 printer = lp_const_servicename(snum);
3781
3782                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3783                         printer, snum));
3784
3785                 result = winreg_create_printer(mem_ctx,
3786                                                server_info,
3787                                                NULL,
3788                                                printer);
3789                 if (!W_ERROR_IS_OK(result)) {
3790                         goto out;
3791                 }
3792
3793                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3794                                             union spoolss_PrinterInfo,
3795                                             count + 1);
3796                 if (!info) {
3797                         result = WERR_NOMEM;
3798                         goto out;
3799                 }
3800
3801                 result = winreg_get_printer(mem_ctx, server_info,
3802                                             NULL, printer, &info2);
3803                 if (!W_ERROR_IS_OK(result)) {
3804                         goto out;
3805                 }
3806
3807                 switch (level) {
3808                 case 0:
3809                         result = construct_printer_info0(info, server_info, info2,
3810                                                          &info[count].info0, snum);
3811                         break;
3812                 case 1:
3813                         result = construct_printer_info1(info, info2, flags,
3814                                                          &info[count].info1, snum);
3815                         break;
3816                 case 2:
3817                         result = construct_printer_info2(info, info2,
3818                                                          &info[count].info2, snum);
3819                         break;
3820                 case 4:
3821                         result = construct_printer_info4(info, info2,
3822                                                          &info[count].info4, snum);
3823                         break;
3824                 case 5:
3825                         result = construct_printer_info5(info, info2,
3826                                                          &info[count].info5, snum);
3827                         break;
3828
3829                 default:
3830                         result = WERR_UNKNOWN_LEVEL;
3831                         goto out;
3832                 }
3833
3834                 if (!W_ERROR_IS_OK(result)) {
3835                         goto out;
3836                 }
3837
3838                 count++;
3839         }
3840
3841         *count_p = count;
3842         *info_p = info;
3843
3844  out:
3845         if (!W_ERROR_IS_OK(result)) {
3846                 TALLOC_FREE(info);
3847                 return result;
3848         }
3849
3850         *info_p = info;
3851
3852         return WERR_OK;
3853 }
3854
3855 /********************************************************************
3856  * handle enumeration of printers at level 0
3857  ********************************************************************/
3858
3859 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3860                                   struct auth_serversupplied_info *server_info,
3861                                   uint32_t flags,
3862                                   const char *servername,
3863                                   union spoolss_PrinterInfo **info,
3864                                   uint32_t *count)
3865 {
3866         DEBUG(4,("enum_all_printers_info_0\n"));
3867
3868         return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3869 }
3870
3871
3872 /********************************************************************
3873 ********************************************************************/
3874
3875 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3876                                        struct auth_serversupplied_info *server_info,
3877                                        uint32_t flags,
3878                                        union spoolss_PrinterInfo **info,
3879                                        uint32_t *count)
3880 {
3881         DEBUG(4,("enum_all_printers_info_1\n"));
3882
3883         return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3884 }
3885
3886 /********************************************************************
3887  enum_all_printers_info_1_local.
3888 *********************************************************************/
3889
3890 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3891                                              struct auth_serversupplied_info *server_info,
3892                                              union spoolss_PrinterInfo **info,
3893                                              uint32_t *count)
3894 {
3895         DEBUG(4,("enum_all_printers_info_1_local\n"));
3896
3897         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3898 }
3899
3900 /********************************************************************
3901  enum_all_printers_info_1_name.
3902 *********************************************************************/
3903
3904 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3905                                             struct auth_serversupplied_info *server_info,
3906                                             const char *name,
3907                                             union spoolss_PrinterInfo **info,
3908                                             uint32_t *count)
3909 {
3910         const char *s = name;
3911
3912         DEBUG(4,("enum_all_printers_info_1_name\n"));
3913
3914         if ((name[0] == '\\') && (name[1] == '\\')) {
3915                 s = name + 2;
3916         }
3917
3918         if (!is_myname_or_ipaddr(s)) {
3919                 return WERR_INVALID_NAME;
3920         }
3921
3922         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3923 }
3924
3925 /********************************************************************
3926  enum_all_printers_info_1_network.
3927 *********************************************************************/
3928
3929 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3930                                                struct auth_serversupplied_info *server_info,
3931                                                const char *name,
3932                                                union spoolss_PrinterInfo **info,
3933                                                uint32_t *count)
3934 {
3935         const char *s = name;
3936
3937         DEBUG(4,("enum_all_printers_info_1_network\n"));
3938
3939         /* If we respond to a enum_printers level 1 on our name with flags
3940            set to PRINTER_ENUM_REMOTE with a list of printers then these
3941            printers incorrectly appear in the APW browse list.
3942            Specifically the printers for the server appear at the workgroup
3943            level where all the other servers in the domain are
3944            listed. Windows responds to this call with a
3945            WERR_CAN_NOT_COMPLETE so we should do the same. */
3946
3947         if (name[0] == '\\' && name[1] == '\\') {
3948                  s = name + 2;
3949         }
3950
3951         if (is_myname_or_ipaddr(s)) {
3952                  return WERR_CAN_NOT_COMPLETE;
3953         }
3954
3955         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3956 }
3957
3958 /********************************************************************
3959  * api_spoolss_enumprinters
3960  *
3961  * called from api_spoolss_enumprinters (see this to understand)
3962  ********************************************************************/
3963
3964 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3965                                        struct auth_serversupplied_info *server_info,
3966                                        union spoolss_PrinterInfo **info,
3967                                        uint32_t *count)
3968 {
3969         DEBUG(4,("enum_all_printers_info_2\n"));
3970
3971         return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3972 }
3973
3974 /********************************************************************
3975  * handle enumeration of printers at level 1
3976  ********************************************************************/
3977
3978 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3979                                   struct auth_serversupplied_info *server_info,
3980                                   uint32_t flags,
3981                                   const char *name,
3982                                   union spoolss_PrinterInfo **info,
3983                                   uint32_t *count)
3984 {
3985         /* Not all the flags are equals */
3986
3987         if (flags & PRINTER_ENUM_LOCAL) {
3988                 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
3989         }
3990
3991         if (flags & PRINTER_ENUM_NAME) {
3992                 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
3993         }
3994
3995         if (flags & PRINTER_ENUM_NETWORK) {
3996                 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
3997         }
3998
3999         return WERR_OK; /* NT4sp5 does that */
4000 }
4001
4002 /********************************************************************
4003  * handle enumeration of printers at level 2
4004  ********************************************************************/
4005
4006 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4007                                   struct auth_serversupplied_info *server_info,
4008                                   uint32_t flags,
4009                                   const char *servername,
4010                                   union spoolss_PrinterInfo **info,
4011                                   uint32_t *count)
4012 {
4013         if (flags & PRINTER_ENUM_LOCAL) {
4014                 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4015         }
4016
4017         if (flags & PRINTER_ENUM_NAME) {
4018                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4019                         return WERR_INVALID_NAME;
4020                 }
4021
4022                 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4023         }
4024
4025         if (flags & PRINTER_ENUM_REMOTE) {
4026                 return WERR_UNKNOWN_LEVEL;
4027         }
4028
4029         return WERR_OK;
4030 }
4031
4032 /********************************************************************
4033  * handle enumeration of printers at level 4
4034  ********************************************************************/
4035
4036 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4037                                   struct auth_serversupplied_info *server_info,
4038                                   uint32_t flags,
4039                                   const char *servername,
4040                                   union spoolss_PrinterInfo **info,
4041                                   uint32_t *count)
4042 {
4043         DEBUG(4,("enum_all_printers_info_4\n"));
4044
4045         return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4046 }
4047
4048
4049 /********************************************************************
4050  * handle enumeration of printers at level 5
4051  ********************************************************************/
4052
4053 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4054                                   struct auth_serversupplied_info *server_info,
4055                                   uint32_t flags,
4056                                   const char *servername,
4057                                   union spoolss_PrinterInfo **info,
4058                                   uint32_t *count)
4059 {
4060         DEBUG(4,("enum_all_printers_info_5\n"));
4061
4062         return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4063 }
4064
4065 /****************************************************************
4066  _spoolss_EnumPrinters
4067 ****************************************************************/
4068
4069 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4070                              struct spoolss_EnumPrinters *r)
4071 {
4072         const char *name = NULL;
4073         WERROR result;
4074
4075         /* that's an [in out] buffer */
4076
4077         if (!r->in.buffer && (r->in.offered != 0)) {
4078                 return WERR_INVALID_PARAM;
4079         }
4080
4081         DEBUG(4,("_spoolss_EnumPrinters\n"));
4082
4083         *r->out.needed = 0;
4084         *r->out.count = 0;
4085         *r->out.info = NULL;
4086
4087         /*
4088          * Level 1:
4089          *          flags==PRINTER_ENUM_NAME
4090          *           if name=="" then enumerates all printers
4091          *           if name!="" then enumerate the printer
4092          *          flags==PRINTER_ENUM_REMOTE
4093          *          name is NULL, enumerate printers
4094          * Level 2: name!="" enumerates printers, name can't be NULL
4095          * Level 3: doesn't exist
4096          * Level 4: does a local registry lookup
4097          * Level 5: same as Level 2
4098          */
4099
4100         if (r->in.server) {
4101                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4102                 W_ERROR_HAVE_NO_MEMORY(name);
4103         }
4104
4105         switch (r->in.level) {
4106         case 0:
4107                 result = enumprinters_level0(p->mem_ctx, p->server_info,
4108                                              r->in.flags, name,
4109                                              r->out.info, r->out.count);
4110                 break;
4111         case 1:
4112                 result = enumprinters_level1(p->mem_ctx, p->server_info,
4113                                              r->in.flags, name,
4114                                              r->out.info, r->out.count);
4115                 break;
4116         case 2:
4117                 result = enumprinters_level2(p->mem_ctx, p->server_info,
4118                                              r->in.flags, name,
4119                                              r->out.info, r->out.count);
4120                 break;
4121         case 4:
4122                 result = enumprinters_level4(p->mem_ctx, p->server_info,
4123                                              r->in.flags, name,
4124                                              r->out.info, r->out.count);
4125                 break;
4126         case 5:
4127                 result = enumprinters_level5(p->mem_ctx, p->server_info,
4128                                              r->in.flags, name,
4129                                              r->out.info, r->out.count);
4130                 break;
4131         default:
4132                 return WERR_UNKNOWN_LEVEL;
4133         }
4134
4135         if (!W_ERROR_IS_OK(result)) {
4136                 return result;
4137         }
4138
4139         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4140                                                      spoolss_EnumPrinters, 
4141                                                      *r->out.info, r->in.level,
4142                                                      *r->out.count);
4143         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4144         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4145
4146         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4147 }
4148
4149 /****************************************************************
4150  _spoolss_GetPrinter
4151 ****************************************************************/
4152
4153 WERROR _spoolss_GetPrinter(pipes_struct *p,
4154                            struct spoolss_GetPrinter *r)
4155 {
4156         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4157         struct spoolss_PrinterInfo2 *info2 = NULL;
4158         WERROR result = WERR_OK;
4159         const char *servername = NULL;
4160         int snum;
4161
4162         /* that's an [in out] buffer */
4163
4164         if (!r->in.buffer && (r->in.offered != 0)) {
4165                 return WERR_INVALID_PARAM;
4166         }
4167
4168         *r->out.needed = 0;
4169
4170         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4171                 return WERR_BADFID;
4172         }
4173
4174         if (Printer != NULL || Printer->servername != NULL) {
4175                 servername = Printer->servername;
4176         }
4177
4178         result = winreg_get_printer(p->mem_ctx,
4179                                     p->server_info,
4180                                     servername,
4181                                     lp_const_servicename(snum),
4182                                     &info2);
4183         if (!W_ERROR_IS_OK(result)) {
4184                 return result;
4185         }
4186
4187         switch (r->in.level) {
4188         case 0:
4189                 result = construct_printer_info0(p->mem_ctx, p->server_info,
4190                                                  info2,
4191                                                  &r->out.info->info0, snum);
4192                 break;
4193         case 1:
4194                 result = construct_printer_info1(p->mem_ctx, info2,
4195                                                  PRINTER_ENUM_ICON8,
4196                                                  &r->out.info->info1, snum);
4197                 break;
4198         case 2:
4199                 result = construct_printer_info2(p->mem_ctx, info2,
4200                                                  &r->out.info->info2, snum);
4201                 break;
4202         case 3:
4203                 result = construct_printer_info3(p->mem_ctx, info2,
4204                                                  &r->out.info->info3, snum);
4205                 break;
4206         case 4:
4207                 result = construct_printer_info4(p->mem_ctx, info2,
4208                                                  &r->out.info->info4, snum);
4209                 break;
4210         case 5:
4211                 result = construct_printer_info5(p->mem_ctx, info2,
4212                                                  &r->out.info->info5, snum);
4213                 break;
4214         case 6:
4215                 result = construct_printer_info6(p->mem_ctx, info2,
4216                                                  &r->out.info->info6, snum);
4217                 break;
4218         case 7:
4219                 result = construct_printer_info7(p->mem_ctx, Printer,
4220                                                  &r->out.info->info7, snum);
4221                 break;
4222         case 8:
4223                 result = construct_printer_info8(p->mem_ctx, info2,
4224                                                  &r->out.info->info8, snum);
4225                 break;
4226         default:
4227                 result = WERR_UNKNOWN_LEVEL;
4228                 break;
4229         }
4230
4231         if (!W_ERROR_IS_OK(result)) {
4232                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4233                           r->in.level, win_errstr(result)));
4234                 TALLOC_FREE(r->out.info);
4235                 return result;
4236         }
4237
4238         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4239                                                r->out.info, r->in.level);
4240         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4241
4242         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4243 }
4244
4245 /********************************************************************
4246  ********************************************************************/
4247
4248 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4249         do { \
4250                 if (in && strlen(in)) { \
4251                         out = talloc_strdup(mem_ctx, in); \
4252                         W_ERROR_HAVE_NO_MEMORY(out); \
4253                 } else { \
4254                         out = NULL; \
4255                 } \
4256         } while (0);
4257
4258 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4259         do { \
4260                 if (in && strlen(in)) { \
4261                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4262                 } else { \
4263                         out = talloc_strdup(mem_ctx, ""); \
4264                 } \
4265                 W_ERROR_HAVE_NO_MEMORY(out); \
4266         } while (0);
4267
4268 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4269                                                   const char **string_array,
4270                                                   const char ***presult,
4271                                                   const char *cservername,
4272                                                   const char *arch,
4273                                                   int version)
4274 {
4275         int i, num_strings = 0;
4276         const char **array = NULL;
4277
4278         if (string_array == NULL) {
4279                 return WERR_INVALID_PARAMETER;;
4280         }
4281
4282         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4283                 const char *str = NULL;
4284
4285                 if (cservername == NULL || arch == NULL) {
4286                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4287                 } else {
4288                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4289                 }
4290
4291                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4292                         TALLOC_FREE(array);
4293                         return WERR_NOMEM;
4294                 }
4295         }
4296
4297         if (i > 0) {
4298                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4299                              &array, &num_strings);
4300         }
4301
4302         if (presult) {
4303                 *presult = array;
4304         }
4305
4306         return WERR_OK;
4307 }
4308
4309 /********************************************************************
4310  * fill a spoolss_DriverInfo1 struct
4311  ********************************************************************/
4312
4313 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4314                                         struct spoolss_DriverInfo1 *r,
4315                                         const struct spoolss_DriverInfo8 *driver,
4316                                         const char *servername)
4317 {
4318         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4319         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4320
4321         return WERR_OK;
4322 }
4323
4324 /********************************************************************
4325  * fill a spoolss_DriverInfo2 struct
4326  ********************************************************************/
4327
4328 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4329                                         struct spoolss_DriverInfo2 *r,
4330                                         const struct spoolss_DriverInfo8 *driver,
4331                                         const char *servername)
4332
4333 {
4334         const char *cservername = canon_servername(servername);
4335
4336         r->version              = driver->version;
4337
4338         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4339         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4340         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4341         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4342
4343         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4344                                driver->architecture,
4345                                driver->version,
4346                                driver->driver_path,
4347                                r->driver_path);
4348
4349         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4350                                driver->architecture,
4351                                driver->version,
4352                                driver->data_file,
4353                                r->data_file);
4354
4355         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4356                                driver->architecture,
4357                                driver->version,
4358                                driver->config_file,
4359                                r->config_file);
4360
4361         return WERR_OK;
4362 }
4363
4364 /********************************************************************
4365  * fill a spoolss_DriverInfo3 struct
4366  ********************************************************************/
4367
4368 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4369                                         struct spoolss_DriverInfo3 *r,
4370                                         const struct spoolss_DriverInfo8 *driver,
4371                                         const char *servername)
4372 {
4373         const char *cservername = canon_servername(servername);
4374
4375         r->version              = driver->version;
4376
4377         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4378         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4379         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4380         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4381
4382         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4383                                driver->architecture,
4384                                driver->version,
4385                                driver->driver_path,
4386                                r->driver_path);
4387
4388         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4389                                driver->architecture,
4390                                driver->version,
4391                                driver->data_file,
4392                                r->data_file);
4393
4394         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4395                                driver->architecture,
4396                                driver->version,
4397                                driver->config_file,
4398                                r->config_file);
4399
4400         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4401                                driver->architecture,
4402                                driver->version,
4403                                driver->help_file,
4404                                r->help_file);
4405
4406         FILL_DRIVER_STRING(mem_ctx,
4407                            driver->monitor_name,
4408                            r->monitor_name);
4409
4410         FILL_DRIVER_STRING(mem_ctx,
4411                            driver->default_datatype,
4412                            r->default_datatype);
4413
4414         return string_array_from_driver_info(mem_ctx,
4415                                              driver->dependent_files,
4416                                              &r->dependent_files,
4417                                              cservername,
4418                                              driver->architecture,
4419                                              driver->version);
4420 }
4421
4422 /********************************************************************
4423  * fill a spoolss_DriverInfo4 struct
4424  ********************************************************************/
4425
4426 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4427                                         struct spoolss_DriverInfo4 *r,
4428                                         const struct spoolss_DriverInfo8 *driver,
4429                                         const char *servername)
4430 {
4431         const char *cservername = canon_servername(servername);
4432         WERROR result;
4433
4434         r->version              = driver->version;
4435
4436         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4437         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4438         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4439         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4440
4441         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4442                                driver->architecture,
4443                                driver->version,
4444                                driver->driver_path,
4445                                r->driver_path);
4446
4447         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4448                                driver->architecture,
4449                                driver->version,
4450                                driver->data_file,
4451                                r->data_file);
4452
4453         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4454                                driver->architecture,
4455                                driver->version,
4456                                driver->config_file,
4457                                r->config_file);
4458
4459         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4460                                driver->architecture,
4461                                driver->version,
4462                                driver->help_file,
4463                                r->help_file);
4464
4465         result = string_array_from_driver_info(mem_ctx,
4466                                                driver->dependent_files,
4467                                                &r->dependent_files,
4468                                                cservername,
4469                                                driver->architecture,
4470                                                driver->version);
4471         if (!W_ERROR_IS_OK(result)) {
4472                 return result;
4473         }
4474
4475         FILL_DRIVER_STRING(mem_ctx,
4476                            driver->monitor_name,
4477                            r->monitor_name);
4478
4479         FILL_DRIVER_STRING(mem_ctx,
4480                            driver->default_datatype,
4481                            r->default_datatype);
4482
4483
4484         result = string_array_from_driver_info(mem_ctx,
4485                                                driver->previous_names,
4486                                                &r->previous_names,
4487                                                NULL, NULL, 0);
4488
4489         return result;
4490 }
4491
4492 /********************************************************************
4493  * fill a spoolss_DriverInfo5 struct
4494  ********************************************************************/
4495
4496 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4497                                         struct spoolss_DriverInfo5 *r,
4498                                         const struct spoolss_DriverInfo8 *driver,
4499                                         const char *servername)
4500 {
4501         const char *cservername = canon_servername(servername);
4502
4503         r->version              = driver->version;
4504
4505         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4506         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4507         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4508         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4509
4510         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4511                                driver->architecture,
4512                                driver->version,
4513                                driver->driver_path,
4514                                r->driver_path);
4515
4516         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4517                                driver->architecture,
4518                                driver->version,
4519                                driver->data_file,
4520                                r->data_file);
4521
4522         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4523                                driver->architecture,
4524                                driver->version,
4525                                driver->config_file,
4526                                r->config_file);
4527
4528         r->driver_attributes    = 0;
4529         r->config_version       = 0;
4530         r->driver_version       = 0;
4531
4532         return WERR_OK;
4533 }
4534 /********************************************************************
4535  * fill a spoolss_DriverInfo6 struct
4536  ********************************************************************/
4537
4538 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4539                                         struct spoolss_DriverInfo6 *r,
4540                                         const struct spoolss_DriverInfo8 *driver,
4541                                         const char *servername)
4542 {
4543         const char *cservername = canon_servername(servername);
4544         WERROR result;
4545
4546         r->version              = driver->version;
4547
4548         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4549         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4550         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4551         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4552
4553         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4554                                driver->architecture,
4555                                driver->version,
4556                                driver->driver_path,
4557                                r->driver_path);
4558
4559         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4560                                driver->architecture,
4561                                driver->version,
4562                                driver->data_file,
4563                                r->data_file);
4564
4565         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4566                                driver->architecture,
4567                                driver->version,
4568                                driver->config_file,
4569                                r->config_file);
4570
4571         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4572                                driver->architecture,
4573                                driver->version,
4574                                driver->help_file,
4575                                r->help_file);
4576
4577         FILL_DRIVER_STRING(mem_ctx,
4578                            driver->monitor_name,
4579                            r->monitor_name);
4580
4581         FILL_DRIVER_STRING(mem_ctx,
4582                            driver->default_datatype,
4583                            r->default_datatype);
4584
4585         result = string_array_from_driver_info(mem_ctx,
4586                                                driver->dependent_files,
4587                                                &r->dependent_files,
4588                                                cservername,
4589                                                driver->architecture,
4590                                                driver->version);
4591         if (!W_ERROR_IS_OK(result)) {
4592                 return result;
4593         }
4594
4595         result = string_array_from_driver_info(mem_ctx,
4596                                                driver->previous_names,
4597                                                &r->previous_names,
4598                                                NULL, NULL, 0);
4599         if (!W_ERROR_IS_OK(result)) {
4600                 return result;
4601         }
4602
4603         r->driver_date          = driver->driver_date;
4604         r->driver_version       = driver->driver_version;
4605
4606         FILL_DRIVER_STRING(mem_ctx,
4607                            driver->manufacturer_name,
4608                            r->manufacturer_name);
4609         FILL_DRIVER_STRING(mem_ctx,
4610                            driver->manufacturer_url,
4611                            r->manufacturer_url);
4612         FILL_DRIVER_STRING(mem_ctx,
4613                            driver->hardware_id,
4614                            r->hardware_id);
4615         FILL_DRIVER_STRING(mem_ctx,
4616                            driver->provider,
4617                            r->provider);
4618
4619         return WERR_OK;
4620 }
4621
4622 /********************************************************************
4623  * fill a spoolss_DriverInfo8 struct
4624  ********************************************************************/
4625
4626 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4627                                         struct spoolss_DriverInfo8 *r,
4628                                         const struct spoolss_DriverInfo8 *driver,
4629                                         const char *servername)
4630 {
4631         const char *cservername = canon_servername(servername);
4632         WERROR result;
4633
4634         r->version              = driver->version;
4635
4636         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4637         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4638         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4639         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4640
4641         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4642                                driver->architecture,
4643                                driver->version,
4644                                driver->driver_path,
4645                                r->driver_path);
4646
4647         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4648                                driver->architecture,
4649                                driver->version,
4650                                driver->data_file,
4651                                r->data_file);
4652
4653         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4654                                driver->architecture,
4655                                driver->version,
4656                                driver->config_file,
4657                                r->config_file);
4658
4659         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4660                                driver->architecture,
4661                                driver->version,
4662                                driver->help_file,
4663                                r->help_file);
4664
4665         FILL_DRIVER_STRING(mem_ctx,
4666                            driver->monitor_name,
4667                            r->monitor_name);
4668
4669         FILL_DRIVER_STRING(mem_ctx,
4670                            driver->default_datatype,
4671                            r->default_datatype);
4672
4673         result = string_array_from_driver_info(mem_ctx,
4674                                                driver->dependent_files,
4675                                                &r->dependent_files,
4676                                                cservername,
4677                                                driver->architecture,
4678                                                driver->version);
4679         if (!W_ERROR_IS_OK(result)) {
4680                 return result;
4681         }
4682
4683         result = string_array_from_driver_info(mem_ctx,
4684                                                driver->previous_names,
4685                                                &r->previous_names,
4686                                                NULL, NULL, 0);
4687         if (!W_ERROR_IS_OK(result)) {
4688                 return result;
4689         }
4690
4691         r->driver_date          = driver->driver_date;
4692         r->driver_version       = driver->driver_version;
4693
4694         FILL_DRIVER_STRING(mem_ctx,
4695                            driver->manufacturer_name,
4696                            r->manufacturer_name);
4697         FILL_DRIVER_STRING(mem_ctx,
4698                            driver->manufacturer_url,
4699                            r->manufacturer_url);
4700         FILL_DRIVER_STRING(mem_ctx,
4701                            driver->hardware_id,
4702                            r->hardware_id);
4703         FILL_DRIVER_STRING(mem_ctx,
4704                            driver->provider,
4705                            r->provider);
4706
4707         FILL_DRIVER_STRING(mem_ctx,
4708                            driver->print_processor,
4709                            r->print_processor);
4710         FILL_DRIVER_STRING(mem_ctx,
4711                            driver->vendor_setup,
4712                            r->vendor_setup);
4713
4714         result = string_array_from_driver_info(mem_ctx,
4715                                                driver->color_profiles,
4716                                                &r->color_profiles,
4717                                                NULL, NULL, 0);
4718         if (!W_ERROR_IS_OK(result)) {
4719                 return result;
4720         }
4721
4722         FILL_DRIVER_STRING(mem_ctx,
4723                            driver->inf_path,
4724                            r->inf_path);
4725
4726         r->printer_driver_attributes    = driver->printer_driver_attributes;
4727
4728         result = string_array_from_driver_info(mem_ctx,
4729                                                driver->core_driver_dependencies,
4730                                                &r->core_driver_dependencies,
4731                                                NULL, NULL, 0);
4732         if (!W_ERROR_IS_OK(result)) {
4733                 return result;
4734         }
4735
4736         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4737         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4738
4739         return WERR_OK;
4740 }
4741
4742 #if 0 /* disabled until marshalling issues are resolved - gd */
4743 /********************************************************************
4744  ********************************************************************/
4745
4746 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4747                                           struct spoolss_DriverFileInfo *r,
4748                                           const char *cservername,
4749                                           const char *file_name,
4750                                           enum spoolss_DriverFileType file_type,
4751                                           uint32_t file_version)
4752 {
4753         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4754                                           cservername, file_name);
4755         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4756         r->file_type    = file_type;
4757         r->file_version = file_version;
4758
4759         return WERR_OK;
4760 }
4761
4762 /********************************************************************
4763  ********************************************************************/
4764
4765 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4766                                                  const struct spoolss_DriverInfo8 *driver,
4767                                                  const char *cservername,
4768                                                  struct spoolss_DriverFileInfo **info_p,
4769                                                  uint32_t *count_p)
4770 {
4771         struct spoolss_DriverFileInfo *info = NULL;
4772         uint32_t count = 0;
4773         WERROR result;
4774         uint32_t i;
4775
4776         *info_p = NULL;
4777         *count_p = 0;
4778
4779         if (strlen(driver->driver_path)) {
4780                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4781                                             struct spoolss_DriverFileInfo,
4782                                             count + 1);
4783                 W_ERROR_HAVE_NO_MEMORY(info);
4784                 result = fill_spoolss_DriverFileInfo(info,
4785                                                      &info[count],
4786                                                      cservername,
4787                                                      driver->driver_path,
4788                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4789                                                      0);
4790                 W_ERROR_NOT_OK_RETURN(result);
4791                 count++;
4792         }
4793
4794         if (strlen(driver->config_file)) {
4795                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4796                                             struct spoolss_DriverFileInfo,
4797                                             count + 1);
4798                 W_ERROR_HAVE_NO_MEMORY(info);
4799                 result = fill_spoolss_DriverFileInfo(info,
4800                                                      &info[count],
4801                                                      cservername,
4802                                                      driver->config_file,
4803                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4804                                                      0);
4805                 W_ERROR_NOT_OK_RETURN(result);
4806                 count++;
4807         }
4808
4809         if (strlen(driver->data_file)) {
4810                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4811                                             struct spoolss_DriverFileInfo,
4812                                             count + 1);
4813                 W_ERROR_HAVE_NO_MEMORY(info);
4814                 result = fill_spoolss_DriverFileInfo(info,
4815                                                      &info[count],
4816                                                      cservername,
4817                                                      driver->data_file,
4818                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4819                                                      0);
4820                 W_ERROR_NOT_OK_RETURN(result);
4821                 count++;
4822         }
4823
4824         if (strlen(driver->help_file)) {
4825                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4826                                             struct spoolss_DriverFileInfo,
4827                                             count + 1);
4828                 W_ERROR_HAVE_NO_MEMORY(info);
4829                 result = fill_spoolss_DriverFileInfo(info,
4830                                                      &info[count],
4831                                                      cservername,
4832                                                      driver->help_file,
4833                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4834                                                      0);
4835                 W_ERROR_NOT_OK_RETURN(result);
4836                 count++;
4837         }
4838
4839         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4840                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4841                                             struct spoolss_DriverFileInfo,
4842                                             count + 1);
4843                 W_ERROR_HAVE_NO_MEMORY(info);
4844                 result = fill_spoolss_DriverFileInfo(info,
4845                                                      &info[count],
4846                                                      cservername,
4847                                                      driver->dependent_files[i],
4848                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4849                                                      0);
4850                 W_ERROR_NOT_OK_RETURN(result);
4851                 count++;
4852         }
4853
4854         *info_p = info;
4855         *count_p = count;
4856
4857         return WERR_OK;
4858 }
4859
4860 /********************************************************************
4861  * fill a spoolss_DriverInfo101 struct
4862  ********************************************************************/
4863
4864 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4865                                           struct spoolss_DriverInfo101 *r,
4866                                           const struct spoolss_DriverInfo8 *driver,
4867                                           const char *servername)
4868 {
4869         const char *cservername = canon_servername(servername);
4870         WERROR result;
4871
4872         r->version              = driver->version;
4873
4874         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4875         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4876         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4877         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4878
4879         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4880                                                     cservername,
4881                                                     &r->file_info,
4882                                                     &r->file_count);
4883         if (!W_ERROR_IS_OK(result)) {
4884                 return result;
4885         }
4886
4887         FILL_DRIVER_STRING(mem_ctx,
4888                            driver->monitor_name,
4889                            r->monitor_name);
4890
4891         FILL_DRIVER_STRING(mem_ctx,
4892                            driver->default_datatype,
4893                            r->default_datatype);
4894
4895         result = string_array_from_driver_info(mem_ctx,
4896                                                driver->previous_names,
4897                                                &r->previous_names,
4898                                                NULL, NULL, 0);
4899         if (!W_ERROR_IS_OK(result)) {
4900                 return result;
4901         }
4902
4903         r->driver_date          = driver->driver_date;
4904         r->driver_version       = driver->driver_version;
4905
4906         FILL_DRIVER_STRING(mem_ctx,
4907                            driver->manufacturer_name,
4908                            r->manufacturer_name);
4909         FILL_DRIVER_STRING(mem_ctx,
4910                            driver->manufacturer_url,
4911                            r->manufacturer_url);
4912         FILL_DRIVER_STRING(mem_ctx,
4913                            driver->hardware_id,
4914                            r->hardware_id);
4915         FILL_DRIVER_STRING(mem_ctx,
4916                            driver->provider,
4917                            r->provider);
4918
4919         return WERR_OK;
4920 }
4921 #endif
4922 /********************************************************************
4923  ********************************************************************/
4924
4925 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4926                                                   struct auth_serversupplied_info *server_info,
4927                                                   uint32_t level,
4928                                                   union spoolss_DriverInfo *r,
4929                                                   int snum,
4930                                                   const char *servername,
4931                                                   const char *architecture,
4932                                                   uint32_t version)
4933 {
4934         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4935         struct spoolss_DriverInfo8 *driver;
4936         WERROR result;
4937
4938         result = winreg_get_printer(mem_ctx,
4939                                     server_info,
4940                                     servername,
4941                                     lp_const_servicename(snum),
4942                                     &pinfo2);
4943
4944         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4945                 win_errstr(result)));
4946
4947         if (!W_ERROR_IS_OK(result)) {
4948                 return WERR_INVALID_PRINTER_NAME;
4949         }
4950
4951         result = winreg_get_driver(mem_ctx, server_info, architecture,
4952                                    pinfo2->drivername, version, &driver);
4953
4954         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4955                 win_errstr(result)));
4956
4957         if (!W_ERROR_IS_OK(result)) {
4958                 /*
4959                  * Is this a W2k client ?
4960                  */
4961
4962                 if (version < 3) {
4963                         talloc_free(pinfo2);
4964                         return WERR_UNKNOWN_PRINTER_DRIVER;
4965                 }
4966
4967                 /* Yes - try again with a WinNT driver. */
4968                 version = 2;
4969                 result = winreg_get_driver(mem_ctx, server_info, architecture,
4970                                            pinfo2->drivername,
4971                                            version, &driver);
4972                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4973                         win_errstr(result)));
4974                 if (!W_ERROR_IS_OK(result)) {
4975                         talloc_free(pinfo2);
4976                         return WERR_UNKNOWN_PRINTER_DRIVER;
4977                 }
4978         }
4979
4980         switch (level) {
4981         case 1:
4982                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4983                 break;
4984         case 2:
4985                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4986                 break;
4987         case 3:
4988                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4989                 break;
4990         case 4:
4991                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4992                 break;
4993         case 5:
4994                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4995                 break;
4996         case 6:
4997                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4998                 break;
4999         case 8:
5000                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5001                 break;
5002 #if 0 /* disabled until marshalling issues are resolved - gd */
5003         case 101:
5004                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5005                 break;
5006 #endif
5007         default:
5008                 result = WERR_UNKNOWN_LEVEL;
5009                 break;
5010         }
5011
5012         talloc_free(pinfo2);
5013         talloc_free(driver);
5014
5015         return result;
5016 }
5017
5018 /****************************************************************
5019  _spoolss_GetPrinterDriver2
5020 ****************************************************************/
5021
5022 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5023                                   struct spoolss_GetPrinterDriver2 *r)
5024 {
5025         Printer_entry *printer;
5026         WERROR result;
5027
5028         int snum;
5029
5030         /* that's an [in out] buffer */
5031
5032         if (!r->in.buffer && (r->in.offered != 0)) {
5033                 return WERR_INVALID_PARAM;
5034         }
5035
5036         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5037
5038         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5039                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5040                 return WERR_INVALID_PRINTER_NAME;
5041         }
5042
5043         *r->out.needed = 0;
5044         *r->out.server_major_version = 0;
5045         *r->out.server_minor_version = 0;
5046
5047         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5048                 return WERR_BADFID;
5049         }
5050
5051         result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
5052                                                      r->in.level, r->out.info,
5053                                                      snum, printer->servername,
5054                                                      r->in.architecture,
5055                                                      r->in.client_major_version);
5056         if (!W_ERROR_IS_OK(result)) {
5057                 TALLOC_FREE(r->out.info);
5058                 return result;
5059         }
5060
5061         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5062                                                r->out.info, r->in.level);
5063         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5064
5065         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5066 }
5067
5068
5069 /****************************************************************
5070  _spoolss_StartPagePrinter
5071 ****************************************************************/
5072
5073 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5074                                  struct spoolss_StartPagePrinter *r)
5075 {
5076         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5077
5078         if (!Printer) {
5079                 DEBUG(3,("_spoolss_StartPagePrinter: "
5080                         "Error in startpageprinter printer handle\n"));
5081                 return WERR_BADFID;
5082         }
5083
5084         Printer->page_started = true;
5085         return WERR_OK;
5086 }
5087
5088 /****************************************************************
5089  _spoolss_EndPagePrinter
5090 ****************************************************************/
5091
5092 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5093                                struct spoolss_EndPagePrinter *r)
5094 {
5095         int snum;
5096
5097         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5098
5099         if (!Printer) {
5100                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5101                         OUR_HANDLE(r->in.handle)));
5102                 return WERR_BADFID;
5103         }
5104
5105         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5106                 return WERR_BADFID;
5107
5108         Printer->page_started = false;
5109         print_job_endpage(snum, Printer->jobid);
5110
5111         return WERR_OK;
5112 }
5113
5114 /****************************************************************
5115  _spoolss_StartDocPrinter
5116 ****************************************************************/
5117
5118 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5119                                 struct spoolss_StartDocPrinter *r)
5120 {
5121         struct spoolss_DocumentInfo1 *info_1;
5122         int snum;
5123         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5124
5125         if (!Printer) {
5126                 DEBUG(2,("_spoolss_StartDocPrinter: "
5127                         "Invalid handle (%s:%u:%u)\n",
5128                         OUR_HANDLE(r->in.handle)));
5129                 return WERR_BADFID;
5130         }
5131
5132         if (r->in.level != 1) {
5133                 return WERR_UNKNOWN_LEVEL;
5134         }
5135
5136         info_1 = r->in.info.info1;
5137
5138         /*
5139          * a nice thing with NT is it doesn't listen to what you tell it.
5140          * when asked to send _only_ RAW datas, it tries to send datas
5141          * in EMF format.
5142          *
5143          * So I add checks like in NT Server ...
5144          */
5145
5146         if (info_1->datatype) {
5147                 if (strcmp(info_1->datatype, "RAW") != 0) {
5148                         *r->out.job_id = 0;
5149                         return WERR_INVALID_DATATYPE;
5150                 }
5151         }
5152
5153         /* get the share number of the printer */
5154         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5155                 return WERR_BADFID;
5156         }
5157
5158         Printer->jobid = print_job_start(p->server_info, snum,
5159                                          info_1->document_name,
5160                                          Printer->devmode);
5161
5162         /* An error occured in print_job_start() so return an appropriate
5163            NT error code. */
5164
5165         if (Printer->jobid == -1) {
5166                 return map_werror_from_unix(errno);
5167         }
5168
5169         Printer->document_started = true;
5170         *r->out.job_id = Printer->jobid;
5171
5172         return WERR_OK;
5173 }
5174
5175 /****************************************************************
5176  _spoolss_EndDocPrinter
5177 ****************************************************************/
5178
5179 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5180                               struct spoolss_EndDocPrinter *r)
5181 {
5182         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5183         int snum;
5184
5185         if (!Printer) {
5186                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5187                         OUR_HANDLE(r->in.handle)));
5188                 return WERR_BADFID;
5189         }
5190
5191         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5192                 return WERR_BADFID;
5193         }
5194
5195         Printer->document_started = false;
5196         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5197         /* error codes unhandled so far ... */
5198
5199         return WERR_OK;
5200 }
5201
5202 /****************************************************************
5203  _spoolss_WritePrinter
5204 ****************************************************************/
5205
5206 WERROR _spoolss_WritePrinter(pipes_struct *p,
5207                              struct spoolss_WritePrinter *r)
5208 {
5209         ssize_t buffer_written;
5210         int snum;
5211         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5212
5213         if (!Printer) {
5214                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5215                         OUR_HANDLE(r->in.handle)));
5216                 *r->out.num_written = r->in._data_size;
5217                 return WERR_BADFID;
5218         }
5219
5220         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5221                 return WERR_BADFID;
5222
5223         buffer_written = print_job_write(snum, Printer->jobid,
5224                                                    (const char *)r->in.data.data,
5225                                                    (SMB_OFF_T)-1,
5226                                                    (size_t)r->in._data_size);
5227         if (buffer_written == (ssize_t)-1) {
5228                 *r->out.num_written = 0;
5229                 if (errno == ENOSPC)
5230                         return WERR_NO_SPOOL_SPACE;
5231                 else
5232                         return WERR_ACCESS_DENIED;
5233         }
5234
5235         *r->out.num_written = r->in._data_size;
5236
5237         return WERR_OK;
5238 }
5239
5240 /********************************************************************
5241  * api_spoolss_getprinter
5242  * called from the spoolss dispatcher
5243  *
5244  ********************************************************************/
5245
5246 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5247                               pipes_struct *p)
5248 {
5249         int snum;
5250         WERROR errcode = WERR_BADFUNC;
5251         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5252
5253         if (!Printer) {
5254                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5255                         OUR_HANDLE(handle)));
5256                 return WERR_BADFID;
5257         }
5258
5259         if (!get_printer_snum(p, handle, &snum, NULL))
5260                 return WERR_BADFID;
5261
5262         switch (command) {
5263         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5264                 errcode = print_queue_pause(p->server_info, snum);
5265                 break;
5266         case SPOOLSS_PRINTER_CONTROL_RESUME:
5267         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5268                 errcode = print_queue_resume(p->server_info, snum);
5269                 break;
5270         case SPOOLSS_PRINTER_CONTROL_PURGE:
5271                 errcode = print_queue_purge(p->server_info, snum);
5272                 break;
5273         default:
5274                 return WERR_UNKNOWN_LEVEL;
5275         }
5276
5277         return errcode;
5278 }
5279
5280
5281 /****************************************************************
5282  _spoolss_AbortPrinter
5283  * From MSDN: "Deletes printer's spool file if printer is configured
5284  * for spooling"
5285 ****************************************************************/
5286
5287 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5288                              struct spoolss_AbortPrinter *r)
5289 {
5290         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5291         int             snum;
5292         WERROR          errcode = WERR_OK;
5293
5294         if (!Printer) {
5295                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5296                         OUR_HANDLE(r->in.handle)));
5297                 return WERR_BADFID;
5298         }
5299
5300         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5301                 return WERR_BADFID;
5302
5303         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5304
5305         return errcode;
5306 }
5307
5308 /********************************************************************
5309  * called by spoolss_api_setprinter
5310  * when updating a printer description
5311  ********************************************************************/
5312
5313 static WERROR update_printer_sec(struct policy_handle *handle,
5314                                  pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5315 {
5316         struct spoolss_security_descriptor *new_secdesc = NULL;
5317         struct spoolss_security_descriptor *old_secdesc = NULL;
5318         const char *printer;
5319         WERROR result;
5320         int snum;
5321
5322         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5323
5324         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5325                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5326                          OUR_HANDLE(handle)));
5327
5328                 result = WERR_BADFID;
5329                 goto done;
5330         }
5331
5332         if (secdesc_ctr == NULL) {
5333                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5334                 result = WERR_INVALID_PARAM;
5335                 goto done;
5336         }
5337         printer = lp_const_servicename(snum);
5338
5339         /* Check the user has permissions to change the security
5340            descriptor.  By experimentation with two NT machines, the user
5341            requires Full Access to the printer to change security
5342            information. */
5343
5344         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5345                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5346                 result = WERR_ACCESS_DENIED;
5347                 goto done;
5348         }
5349
5350         /* NT seems to like setting the security descriptor even though
5351            nothing may have actually changed. */
5352         result = winreg_get_printer_secdesc(p->mem_ctx,
5353                                             p->server_info,
5354                                             printer,
5355                                             &old_secdesc);
5356         if (!W_ERROR_IS_OK(result)) {
5357                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5358                 result = WERR_BADFID;
5359                 goto done;
5360         }
5361
5362         if (DEBUGLEVEL >= 10) {
5363                 struct security_acl *the_acl;
5364                 int i;
5365
5366                 the_acl = secdesc_ctr->sd->dacl;
5367                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5368                            printer, the_acl->num_aces));
5369
5370                 for (i = 0; i < the_acl->num_aces; i++) {
5371                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5372                                            &the_acl->aces[i].trustee),
5373                                   the_acl->aces[i].access_mask));
5374                 }
5375
5376                 the_acl = secdesc_ctr->sd->dacl;
5377
5378                 if (the_acl) {
5379                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5380                                    printer, the_acl->num_aces));
5381
5382                         for (i = 0; i < the_acl->num_aces; i++) {
5383                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5384                                                    &the_acl->aces[i].trustee),
5385                                            the_acl->aces[i].access_mask));
5386                         }
5387                 } else {
5388                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5389                 }
5390         }
5391
5392         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5393         if (new_secdesc == NULL) {
5394                 result = WERR_NOMEM;
5395                 goto done;
5396         }
5397
5398         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5399                 result = WERR_OK;
5400                 goto done;
5401         }
5402
5403         result = winreg_set_printer_secdesc(p->mem_ctx,
5404                                             p->server_info,
5405                                             printer,
5406                                             new_secdesc);
5407
5408  done:
5409         return result;
5410 }
5411
5412 /********************************************************************
5413  Canonicalize printer info from a client
5414  ********************************************************************/
5415
5416 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5417                              struct spoolss_SetPrinterInfo2 *info2,
5418                              int snum)
5419 {
5420         fstring printername;
5421         const char *p;
5422
5423         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5424                 "portname=%s drivername=%s comment=%s location=%s\n",
5425                 info2->servername, info2->printername, info2->sharename,
5426                 info2->portname, info2->drivername, info2->comment,
5427                 info2->location));
5428
5429         /* we force some elements to "correct" values */
5430         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5431         if (info2->servername == NULL) {
5432                 return false;
5433         }
5434         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5435         if (info2->sharename == NULL) {
5436                 return false;
5437         }
5438
5439         /* check to see if we allow printername != sharename */
5440         if (lp_force_printername(snum)) {
5441                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5442                                         global_myname(), info2->sharename);
5443         } else {
5444                 /* make sure printername is in \\server\printername format */
5445                 fstrcpy(printername, info2->printername);
5446                 p = printername;
5447                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5448                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5449                                 p++;
5450                 }
5451
5452                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5453                                         global_myname(), p);
5454         }
5455         if (info2->printername == NULL) {
5456                 return false;
5457         }
5458
5459         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5460         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5461
5462         return true;
5463 }
5464
5465 /****************************************************************************
5466 ****************************************************************************/
5467
5468 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5469 {
5470         char *cmd = lp_addport_cmd();
5471         char *command = NULL;
5472         int ret;
5473         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5474         bool is_print_op = false;
5475
5476         if ( !*cmd ) {
5477                 return WERR_ACCESS_DENIED;
5478         }
5479
5480         command = talloc_asprintf(ctx,
5481                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5482         if (!command) {
5483                 return WERR_NOMEM;
5484         }
5485
5486         if ( token )
5487                 is_print_op = user_has_privileges( token, &se_printop );
5488
5489         DEBUG(10,("Running [%s]\n", command));
5490
5491         /********* BEGIN SePrintOperatorPrivilege **********/
5492
5493         if ( is_print_op )
5494                 become_root();
5495
5496         ret = smbrun(command, NULL);
5497
5498         if ( is_print_op )
5499                 unbecome_root();
5500
5501         /********* END SePrintOperatorPrivilege **********/
5502
5503         DEBUGADD(10,("returned [%d]\n", ret));
5504
5505         TALLOC_FREE(command);
5506
5507         if ( ret != 0 ) {
5508                 return WERR_ACCESS_DENIED;
5509         }
5510
5511         return WERR_OK;
5512 }
5513
5514 /****************************************************************************
5515 ****************************************************************************/
5516
5517 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5518                       struct spoolss_SetPrinterInfo2 *info2)
5519 {
5520         char *cmd = lp_addprinter_cmd();
5521         char **qlines;
5522         char *command = NULL;
5523         int numlines;
5524         int ret;
5525         int fd;
5526         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5527         bool is_print_op = false;
5528         char *remote_machine = talloc_strdup(ctx, "%m");
5529
5530         if (!remote_machine) {
5531                 return false;
5532         }
5533         remote_machine = talloc_sub_basic(ctx,
5534                                 current_user_info.smb_name,
5535                                 current_user_info.domain,
5536                                 remote_machine);
5537         if (!remote_machine) {
5538                 return false;
5539         }
5540
5541         command = talloc_asprintf(ctx,
5542                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5543                         cmd, info2->printername, info2->sharename,
5544                         info2->portname, info2->drivername,
5545                         info2->location, info2->comment, remote_machine);
5546         if (!command) {
5547                 return false;
5548         }
5549
5550         if ( token )
5551                 is_print_op = user_has_privileges( token, &se_printop );
5552
5553         DEBUG(10,("Running [%s]\n", command));
5554
5555         /********* BEGIN SePrintOperatorPrivilege **********/
5556
5557         if ( is_print_op )
5558                 become_root();
5559
5560         if ( (ret = smbrun(command, &fd)) == 0 ) {
5561                 /* Tell everyone we updated smb.conf. */
5562                 message_send_all(smbd_messaging_context(),
5563                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5564         }
5565
5566         if ( is_print_op )
5567                 unbecome_root();
5568
5569         /********* END SePrintOperatorPrivilege **********/
5570
5571         DEBUGADD(10,("returned [%d]\n", ret));
5572
5573         TALLOC_FREE(command);
5574         TALLOC_FREE(remote_machine);
5575
5576         if ( ret != 0 ) {
5577                 if (fd != -1)
5578                         close(fd);
5579                 return false;
5580         }
5581
5582         /* reload our services immediately */
5583         become_root();
5584         reload_services(false);
5585         unbecome_root();
5586
5587         numlines = 0;
5588         /* Get lines and convert them back to dos-codepage */
5589         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5590         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5591         close(fd);
5592
5593         /* Set the portname to what the script says the portname should be. */
5594         /* but don't require anything to be return from the script exit a good error code */
5595
5596         if (numlines) {
5597                 /* Set the portname to what the script says the portname should be. */
5598                 info2->portname = talloc_strdup(ctx, qlines[0]);
5599                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5600         }
5601
5602         TALLOC_FREE(qlines);
5603         return true;
5604 }
5605
5606 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5607                                struct auth_serversupplied_info *server_info,
5608                                int snum,
5609                                struct spoolss_SetPrinterInfo2 *printer,
5610                                struct spoolss_PrinterInfo2 *old_printer)
5611 {
5612         bool force_update = (old_printer == NULL);
5613         const char *dnsdomname;
5614         const char *longname;
5615         const char *uncname;
5616         const char *spooling;
5617         DATA_BLOB buffer;
5618         WERROR result = WERR_OK;
5619
5620         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5621                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5622                 winreg_set_printer_dataex(mem_ctx,
5623                                           server_info,
5624                                           printer->sharename,
5625                                           SPOOL_DSSPOOLER_KEY,
5626                                           SPOOL_REG_DRIVERNAME,
5627                                           REG_SZ,
5628                                           buffer.data,
5629                                           buffer.length);
5630
5631                 if (!force_update) {
5632                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5633                                 printer->drivername));
5634
5635                         notify_printer_driver(snum, printer->drivername);
5636                 }
5637         }
5638
5639         if (force_update || !strequal(printer->comment, old_printer->comment)) {
5640                 push_reg_sz(mem_ctx, &buffer, printer->comment);
5641                 winreg_set_printer_dataex(mem_ctx,
5642                                           server_info,
5643                                           printer->sharename,
5644                                           SPOOL_DSSPOOLER_KEY,
5645                                           SPOOL_REG_DESCRIPTION,
5646                                           REG_SZ,
5647                                           buffer.data,
5648                                           buffer.length);
5649
5650                 if (!force_update) {
5651                         notify_printer_comment(snum, printer->comment);
5652                 }
5653         }
5654
5655         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5656                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5657                 winreg_set_printer_dataex(mem_ctx,
5658                                           server_info,
5659                                           printer->sharename,
5660                                           SPOOL_DSSPOOLER_KEY,
5661                                           SPOOL_REG_PRINTSHARENAME,
5662                                           REG_SZ,
5663                                           buffer.data,
5664                                           buffer.length);
5665
5666                 if (!force_update) {
5667                         notify_printer_sharename(snum, printer->sharename);
5668                 }
5669         }
5670
5671         if (force_update || !strequal(printer->printername, old_printer->printername)) {
5672                 const char *p;
5673
5674                 p = strrchr(printer->printername, '\\' );
5675                 if (p != NULL) {
5676                         p++;
5677                 } else {
5678                         p = printer->printername;
5679                 }
5680
5681                 push_reg_sz(mem_ctx, &buffer, p);
5682                 winreg_set_printer_dataex(mem_ctx,
5683                                           server_info,
5684                                           printer->sharename,
5685                                           SPOOL_DSSPOOLER_KEY,
5686                                           SPOOL_REG_PRINTERNAME,
5687                                           REG_SZ,
5688                                           buffer.data,
5689                                           buffer.length);
5690
5691                 if (!force_update) {
5692                         notify_printer_printername(snum, p);
5693                 }
5694         }
5695
5696         if (force_update || !strequal(printer->portname, old_printer->portname)) {
5697                 push_reg_sz(mem_ctx, &buffer, printer->portname);
5698                 winreg_set_printer_dataex(mem_ctx,
5699                                           server_info,
5700                                           printer->sharename,
5701                                           SPOOL_DSSPOOLER_KEY,
5702                                           SPOOL_REG_PORTNAME,
5703                                           REG_SZ,
5704                                           buffer.data,
5705                                           buffer.length);
5706
5707                 if (!force_update) {
5708                         notify_printer_port(snum, printer->portname);
5709                 }
5710         }
5711
5712         if (force_update || !strequal(printer->location, old_printer->location)) {
5713                 push_reg_sz(mem_ctx, &buffer, printer->location);
5714                 winreg_set_printer_dataex(mem_ctx,
5715                                           server_info,
5716                                           printer->sharename,
5717                                           SPOOL_DSSPOOLER_KEY,
5718                                           SPOOL_REG_LOCATION,
5719                                           REG_SZ,
5720                                           buffer.data,
5721                                           buffer.length);
5722
5723                 if (!force_update) {
5724                         notify_printer_location(snum, printer->location);
5725                 }
5726         }
5727
5728         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
5729                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
5730                 winreg_set_printer_dataex(mem_ctx,
5731                                           server_info,
5732                                           printer->sharename,
5733                                           SPOOL_DSSPOOLER_KEY,
5734                                           SPOOL_REG_PRINTSEPARATORFILE,
5735                                           REG_SZ,
5736                                           buffer.data,
5737                                           buffer.length);
5738
5739                 if (!force_update) {
5740                         notify_printer_location(snum, printer->location);
5741                 }
5742         }
5743
5744         if (force_update || printer->starttime != old_printer->starttime) {
5745                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5746                 SIVAL(buffer.data, 0, printer->starttime);
5747                 winreg_set_printer_dataex(mem_ctx,
5748                                           server_info,
5749                                           printer->sharename,
5750                                           SPOOL_DSSPOOLER_KEY,
5751                                           SPOOL_REG_PRINTSTARTTIME,
5752                                           REG_DWORD,
5753                                           buffer.data,
5754                                           buffer.length);
5755         }
5756
5757         if (force_update || printer->untiltime != old_printer->untiltime) {
5758                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5759                 SIVAL(buffer.data, 0, printer->untiltime);
5760                 winreg_set_printer_dataex(mem_ctx,
5761                                           server_info,
5762                                           printer->sharename,
5763                                           SPOOL_DSSPOOLER_KEY,
5764                                           SPOOL_REG_PRINTENDTIME,
5765                                           REG_DWORD,
5766                                           buffer.data,
5767                                           buffer.length);
5768         }
5769
5770         if (force_update || printer->priority != old_printer->priority) {
5771                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5772                 SIVAL(buffer.data, 0, printer->priority);
5773                 winreg_set_printer_dataex(mem_ctx,
5774                                           server_info,
5775                                           printer->sharename,
5776                                           SPOOL_DSSPOOLER_KEY,
5777                                           SPOOL_REG_PRIORITY,
5778                                           REG_DWORD,
5779                                           buffer.data,
5780                                           buffer.length);
5781         }
5782
5783         if (force_update || printer->attributes != old_printer->attributes) {
5784                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5785                 SIVAL(buffer.data, 0, (printer->attributes &
5786                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
5787                 winreg_set_printer_dataex(mem_ctx,
5788                                           server_info,
5789                                           printer->sharename,
5790                                           SPOOL_DSSPOOLER_KEY,
5791                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
5792                                           REG_DWORD,
5793                                           buffer.data,
5794                                           buffer.length);
5795
5796                 switch (printer->attributes & 0x3) {
5797                         case 0:
5798                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
5799                                 break;
5800                         case 1:
5801                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
5802                                 break;
5803                         case 2:
5804                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
5805                                 break;
5806                         default:
5807                                 spooling = "unknown";
5808                 }
5809                 push_reg_sz(mem_ctx, &buffer, spooling);
5810                 winreg_set_printer_dataex(mem_ctx,
5811                                           server_info,
5812                                           printer->sharename,
5813                                           SPOOL_DSSPOOLER_KEY,
5814                                           SPOOL_REG_PRINTSPOOLING,
5815                                           REG_SZ,
5816                                           buffer.data,
5817                                           buffer.length);
5818         }
5819
5820         push_reg_sz(mem_ctx, &buffer, global_myname());
5821         winreg_set_printer_dataex(mem_ctx,
5822                                   server_info,
5823                                   printer->sharename,
5824                                   SPOOL_DSSPOOLER_KEY,
5825                                   SPOOL_REG_SHORTSERVERNAME,
5826                                   REG_SZ,
5827                                   buffer.data,
5828                                   buffer.length);
5829
5830         dnsdomname = get_mydnsfullname();
5831         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
5832                 longname = talloc_strdup(mem_ctx, dnsdomname);
5833         } else {
5834                 longname = talloc_strdup(mem_ctx, global_myname());
5835         }
5836         if (longname == NULL) {
5837                 result = WERR_NOMEM;
5838                 goto done;
5839         }
5840
5841         push_reg_sz(mem_ctx, &buffer, longname);
5842         winreg_set_printer_dataex(mem_ctx,
5843                                   server_info,
5844                                   printer->sharename,
5845                                   SPOOL_DSSPOOLER_KEY,
5846                                   SPOOL_REG_SERVERNAME,
5847                                   REG_SZ,
5848                                   buffer.data,
5849                                   buffer.length);
5850
5851         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5852                                   global_myname(), printer->sharename);
5853         push_reg_sz(mem_ctx, &buffer, uncname);
5854         winreg_set_printer_dataex(mem_ctx,
5855                                   server_info,
5856                                   printer->sharename,
5857                                   SPOOL_DSSPOOLER_KEY,
5858                                   SPOOL_REG_UNCNAME,
5859                                   REG_SZ,
5860                                   buffer.data,
5861                                   buffer.length);
5862
5863 done:
5864         return result;
5865 }
5866
5867 /********************************************************************
5868  * Called by spoolss_api_setprinter
5869  * when updating a printer description.
5870  ********************************************************************/
5871
5872 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5873                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5874                              struct spoolss_DeviceMode *devmode)
5875 {
5876         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5877         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5878         struct spoolss_PrinterInfo2 *old_printer;
5879         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5880         const char *servername = NULL;
5881         int snum;
5882         WERROR result = WERR_OK;
5883         TALLOC_CTX *tmp_ctx;
5884
5885         DEBUG(8,("update_printer\n"));
5886
5887         tmp_ctx = talloc_new(p->mem_ctx);
5888         if (tmp_ctx == NULL) {
5889                 return WERR_NOMEM;
5890         }
5891
5892         if (!Printer) {
5893                 result = WERR_BADFID;
5894                 goto done;
5895         }
5896
5897         if (!get_printer_snum(p, handle, &snum, NULL)) {
5898                 result = WERR_BADFID;
5899                 goto done;
5900         }
5901
5902         if (Printer != NULL || Printer->servername != NULL) {
5903                 servername = Printer->servername;
5904         }
5905
5906         result = winreg_get_printer(tmp_ctx,
5907                                     p->server_info,
5908                                     servername,
5909                                     lp_const_servicename(snum),
5910                                     &old_printer);
5911         if (!W_ERROR_IS_OK(result)) {
5912                 result = WERR_BADFID;
5913                 goto done;
5914         }
5915
5916         /* Do sanity check on the requested changes for Samba */
5917         if (!check_printer_ok(tmp_ctx, printer, snum)) {
5918                 result = WERR_INVALID_PARAM;
5919                 goto done;
5920         }
5921
5922         /* FIXME!!! If the driver has changed we really should verify that
5923            it is installed before doing much else   --jerry */
5924
5925         /* Check calling user has permission to update printer description */
5926         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5927                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5928                 result = WERR_ACCESS_DENIED;
5929                 goto done;
5930         }
5931
5932         /* Call addprinter hook */
5933         /* Check changes to see if this is really needed */
5934
5935         if (*lp_addprinter_cmd() &&
5936                         (!strequal(printer->drivername, old_printer->drivername) ||
5937                          !strequal(printer->comment, old_printer->comment) ||
5938                          !strequal(printer->portname, old_printer->portname) ||
5939                          !strequal(printer->location, old_printer->location)) )
5940         {
5941                 /* add_printer_hook() will call reload_services() */
5942                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
5943                                       printer) ) {
5944                         result = WERR_ACCESS_DENIED;
5945                         goto done;
5946                 }
5947         }
5948
5949         update_dsspooler(tmp_ctx,
5950                          p->server_info,
5951                          snum,
5952                          printer,
5953                          old_printer);
5954
5955         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5956
5957         if (devmode == NULL) {
5958                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5959         }
5960         result = winreg_update_printer(tmp_ctx,
5961                                        p->server_info,
5962                                        printer->sharename,
5963                                        printer_mask,
5964                                        printer,
5965                                        devmode,
5966                                        NULL);
5967
5968 done:
5969         talloc_free(tmp_ctx);
5970
5971         return result;
5972 }
5973
5974 /****************************************************************************
5975 ****************************************************************************/
5976 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5977                                            struct policy_handle *handle,
5978                                            struct spoolss_SetPrinterInfo7 *info7)
5979 {
5980 #ifdef HAVE_ADS
5981         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5982         WERROR result;
5983         int snum;
5984         Printer_entry *Printer;
5985
5986         if ( lp_security() != SEC_ADS ) {
5987                 return WERR_UNKNOWN_LEVEL;
5988         }
5989
5990         Printer = find_printer_index_by_hnd(p, handle);
5991
5992         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5993
5994         if (!Printer)
5995                 return WERR_BADFID;
5996
5997         if (!get_printer_snum(p, handle, &snum, NULL))
5998                 return WERR_BADFID;
5999
6000         result = winreg_get_printer(p->mem_ctx, p->server_info,
6001                                     Printer->servername,
6002                                     lp_servicename(snum), &pinfo2);
6003         if (!W_ERROR_IS_OK(result)) {
6004                 return WERR_BADFID;
6005         }
6006
6007         nt_printer_publish(pinfo2, p->server_info, pinfo2, info7->action);
6008
6009         TALLOC_FREE(pinfo2);
6010         return WERR_OK;
6011 #else
6012         return WERR_UNKNOWN_LEVEL;
6013 #endif
6014 }
6015
6016 /********************************************************************
6017  ********************************************************************/
6018
6019 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
6020                                      struct spoolss_DeviceMode *devmode)
6021 {
6022         int snum;
6023         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6024         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6025
6026         DEBUG(8,("update_printer_devmode\n"));
6027
6028         if (!Printer) {
6029                 return WERR_BADFID;
6030         }
6031
6032         if (!get_printer_snum(p, handle, &snum, NULL)) {
6033                 return WERR_BADFID;
6034         }
6035
6036         /* Check calling user has permission to update printer description */
6037         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6038                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6039                 return WERR_ACCESS_DENIED;
6040         }
6041
6042         return winreg_update_printer(p->mem_ctx,
6043                                      p->server_info,
6044                                      lp_const_servicename(snum),
6045                                      info2_mask,
6046                                      NULL,
6047                                      devmode,
6048                                      NULL);
6049 }
6050
6051
6052 /****************************************************************
6053  _spoolss_SetPrinter
6054 ****************************************************************/
6055
6056 WERROR _spoolss_SetPrinter(pipes_struct *p,
6057                            struct spoolss_SetPrinter *r)
6058 {
6059         WERROR result;
6060
6061         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6062
6063         if (!Printer) {
6064                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6065                         OUR_HANDLE(r->in.handle)));
6066                 return WERR_BADFID;
6067         }
6068
6069         /* check the level */
6070         switch (r->in.info_ctr->level) {
6071                 case 0:
6072                         return control_printer(r->in.handle, r->in.command, p);
6073                 case 2:
6074                         result = update_printer(p, r->in.handle,
6075                                                 r->in.info_ctr,
6076                                                 r->in.devmode_ctr->devmode);
6077                         if (!W_ERROR_IS_OK(result))
6078                                 return result;
6079                         if (r->in.secdesc_ctr->sd)
6080                                 result = update_printer_sec(r->in.handle, p,
6081                                                             r->in.secdesc_ctr);
6082                         return result;
6083                 case 3:
6084                         return update_printer_sec(r->in.handle, p,
6085                                                   r->in.secdesc_ctr);
6086                 case 7:
6087                         return publish_or_unpublish_printer(p, r->in.handle,
6088                                                             r->in.info_ctr->info.info7);
6089                 case 8:
6090                         return update_printer_devmode(p, r->in.handle,
6091                                                       r->in.devmode_ctr->devmode);
6092                 default:
6093                         return WERR_UNKNOWN_LEVEL;
6094         }
6095 }
6096
6097 /****************************************************************
6098  _spoolss_FindClosePrinterNotify
6099 ****************************************************************/
6100
6101 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6102                                        struct spoolss_FindClosePrinterNotify *r)
6103 {
6104         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6105
6106         if (!Printer) {
6107                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6108                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6109                 return WERR_BADFID;
6110         }
6111
6112         if (Printer->notify.client_connected == true) {
6113                 int snum = -1;
6114
6115                 if ( Printer->printer_type == SPLHND_SERVER)
6116                         snum = -1;
6117                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6118                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6119                         return WERR_BADFID;
6120
6121                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6122         }
6123
6124         Printer->notify.flags=0;
6125         Printer->notify.options=0;
6126         Printer->notify.localmachine[0]='\0';
6127         Printer->notify.printerlocal=0;
6128         TALLOC_FREE(Printer->notify.option);
6129         Printer->notify.client_connected = false;
6130
6131         return WERR_OK;
6132 }
6133
6134 /****************************************************************
6135  _spoolss_AddJob
6136 ****************************************************************/
6137
6138 WERROR _spoolss_AddJob(pipes_struct *p,
6139                        struct spoolss_AddJob *r)
6140 {
6141         if (!r->in.buffer && (r->in.offered != 0)) {
6142                 return WERR_INVALID_PARAM;
6143         }
6144
6145         /* this is what a NT server returns for AddJob. AddJob must fail on
6146          * non-local printers */
6147
6148         if (r->in.level != 1) {
6149                 return WERR_UNKNOWN_LEVEL;
6150         }
6151
6152         return WERR_INVALID_PARAM;
6153 }
6154
6155 /****************************************************************************
6156 fill_job_info1
6157 ****************************************************************************/
6158
6159 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6160                              struct spoolss_JobInfo1 *r,
6161                              const print_queue_struct *queue,
6162                              int position, int snum,
6163                              struct spoolss_PrinterInfo2 *pinfo2)
6164 {
6165         struct tm *t;
6166
6167         t = gmtime(&queue->time);
6168
6169         r->job_id               = queue->job;
6170
6171         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6172         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6173         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6174         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6175         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6176         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6177         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6178         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6179         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6180         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6181         r->text_status          = talloc_strdup(mem_ctx, "");
6182         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6183
6184         r->status               = nt_printj_status(queue->status);
6185         r->priority             = queue->priority;
6186         r->position             = position;
6187         r->total_pages          = queue->page_count;
6188         r->pages_printed        = 0; /* ??? */
6189
6190         init_systemtime(&r->submitted, t);
6191
6192         return WERR_OK;
6193 }
6194
6195 /****************************************************************************
6196 fill_job_info2
6197 ****************************************************************************/
6198
6199 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6200                              struct spoolss_JobInfo2 *r,
6201                              const print_queue_struct *queue,
6202                              int position, int snum,
6203                              struct spoolss_PrinterInfo2 *pinfo2,
6204                              struct spoolss_DeviceMode *devmode)
6205 {
6206         struct tm *t;
6207
6208         t = gmtime(&queue->time);
6209
6210         r->job_id               = queue->job;
6211
6212         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6213         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6214         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6215         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6216         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6217         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6218         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6219         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6220         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6221         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6222         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6223         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6224         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6225         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6226         r->parameters           = talloc_strdup(mem_ctx, "");
6227         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6228         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6229         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6230
6231         r->devmode              = devmode;
6232
6233         r->text_status          = talloc_strdup(mem_ctx, "");
6234         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6235
6236         r->secdesc              = NULL;
6237
6238         r->status               = nt_printj_status(queue->status);
6239         r->priority             = queue->priority;
6240         r->position             = position;
6241         r->start_time           = 0;
6242         r->until_time           = 0;
6243         r->total_pages          = queue->page_count;
6244         r->size                 = queue->size;
6245         init_systemtime(&r->submitted, t);
6246         r->time                 = 0;
6247         r->pages_printed        = 0; /* ??? */
6248
6249         return WERR_OK;
6250 }
6251
6252 /****************************************************************************
6253 fill_job_info3
6254 ****************************************************************************/
6255
6256 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6257                              struct spoolss_JobInfo3 *r,
6258                              const print_queue_struct *queue,
6259                              const print_queue_struct *next_queue,
6260                              int position, int snum,
6261                              struct spoolss_PrinterInfo2 *pinfo2)
6262 {
6263         r->job_id               = queue->job;
6264         r->next_job_id          = 0;
6265         if (next_queue) {
6266                 r->next_job_id  = next_queue->job;
6267         }
6268         r->reserved             = 0;
6269
6270         return WERR_OK;
6271 }
6272
6273 /****************************************************************************
6274  Enumjobs at level 1.
6275 ****************************************************************************/
6276
6277 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6278                               const print_queue_struct *queue,
6279                               uint32_t num_queues, int snum,
6280                               struct spoolss_PrinterInfo2 *pinfo2,
6281                               union spoolss_JobInfo **info_p,
6282                               uint32_t *count)
6283 {
6284         union spoolss_JobInfo *info;
6285         int i;
6286         WERROR result = WERR_OK;
6287
6288         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6289         W_ERROR_HAVE_NO_MEMORY(info);
6290
6291         *count = num_queues;
6292
6293         for (i=0; i<*count; i++) {
6294                 result = fill_job_info1(info,
6295                                         &info[i].info1,
6296                                         &queue[i],
6297                                         i,
6298                                         snum,
6299                                         pinfo2);
6300                 if (!W_ERROR_IS_OK(result)) {
6301                         goto out;
6302                 }
6303         }
6304
6305  out:
6306         if (!W_ERROR_IS_OK(result)) {
6307                 TALLOC_FREE(info);
6308                 *count = 0;
6309                 return result;
6310         }
6311
6312         *info_p = info;
6313
6314         return WERR_OK;
6315 }
6316
6317 /****************************************************************************
6318  Enumjobs at level 2.
6319 ****************************************************************************/
6320
6321 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6322                               const print_queue_struct *queue,
6323                               uint32_t num_queues, int snum,
6324                               struct spoolss_PrinterInfo2 *pinfo2,
6325                               union spoolss_JobInfo **info_p,
6326                               uint32_t *count)
6327 {
6328         union spoolss_JobInfo *info;
6329         int i;
6330         WERROR result = WERR_OK;
6331
6332         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6333         W_ERROR_HAVE_NO_MEMORY(info);
6334
6335         *count = num_queues;
6336
6337         for (i=0; i<*count; i++) {
6338                 struct spoolss_DeviceMode *devmode;
6339
6340                 result = spoolss_create_default_devmode(info,
6341                                                         pinfo2->printername,
6342                                                         &devmode);
6343                 if (!W_ERROR_IS_OK(result)) {
6344                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6345                         goto out;
6346                 }
6347
6348                 result = fill_job_info2(info,
6349                                         &info[i].info2,
6350                                         &queue[i],
6351                                         i,
6352                                         snum,
6353                                         pinfo2,
6354                                         devmode);
6355                 if (!W_ERROR_IS_OK(result)) {
6356                         goto out;
6357                 }
6358         }
6359
6360  out:
6361         if (!W_ERROR_IS_OK(result)) {
6362                 TALLOC_FREE(info);
6363                 *count = 0;
6364                 return result;
6365         }
6366
6367         *info_p = info;
6368
6369         return WERR_OK;
6370 }
6371
6372 /****************************************************************************
6373  Enumjobs at level 3.
6374 ****************************************************************************/
6375
6376 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6377                               const print_queue_struct *queue,
6378                               uint32_t num_queues, int snum,
6379                               struct spoolss_PrinterInfo2 *pinfo2,
6380                               union spoolss_JobInfo **info_p,
6381                               uint32_t *count)
6382 {
6383         union spoolss_JobInfo *info;
6384         int i;
6385         WERROR result = WERR_OK;
6386
6387         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6388         W_ERROR_HAVE_NO_MEMORY(info);
6389
6390         *count = num_queues;
6391
6392         for (i=0; i<*count; i++) {
6393                 const print_queue_struct *next_queue = NULL;
6394
6395                 if (i+1 < *count) {
6396                         next_queue = &queue[i+1];
6397                 }
6398
6399                 result = fill_job_info3(info,
6400                                         &info[i].info3,
6401                                         &queue[i],
6402                                         next_queue,
6403                                         i,
6404                                         snum,
6405                                         pinfo2);
6406                 if (!W_ERROR_IS_OK(result)) {
6407                         goto out;
6408                 }
6409         }
6410
6411  out:
6412         if (!W_ERROR_IS_OK(result)) {
6413                 TALLOC_FREE(info);
6414                 *count = 0;
6415                 return result;
6416         }
6417
6418         *info_p = info;
6419
6420         return WERR_OK;
6421 }
6422
6423 /****************************************************************
6424  _spoolss_EnumJobs
6425 ****************************************************************/
6426
6427 WERROR _spoolss_EnumJobs(pipes_struct *p,
6428                          struct spoolss_EnumJobs *r)
6429 {
6430         WERROR result;
6431         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6432         int snum;
6433         print_status_struct prt_status;
6434         print_queue_struct *queue = NULL;
6435         uint32_t count;
6436
6437         /* that's an [in out] buffer */
6438
6439         if (!r->in.buffer && (r->in.offered != 0)) {
6440                 return WERR_INVALID_PARAM;
6441         }
6442
6443         DEBUG(4,("_spoolss_EnumJobs\n"));
6444
6445         *r->out.needed = 0;
6446         *r->out.count = 0;
6447         *r->out.info = NULL;
6448
6449         /* lookup the printer snum and tdb entry */
6450
6451         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6452                 return WERR_BADFID;
6453         }
6454
6455         result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
6456                                     lp_servicename(snum), &pinfo2);
6457         if (!W_ERROR_IS_OK(result)) {
6458                 return result;
6459         }
6460
6461         count = print_queue_status(snum, &queue, &prt_status);
6462         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6463                 count, prt_status.status, prt_status.message));
6464
6465         if (count == 0) {
6466                 SAFE_FREE(queue);
6467                 TALLOC_FREE(pinfo2);
6468                 return WERR_OK;
6469         }
6470
6471         switch (r->in.level) {
6472         case 1:
6473                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6474                                          pinfo2, r->out.info, r->out.count);
6475                 break;
6476         case 2:
6477                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6478                                          pinfo2, r->out.info, r->out.count);
6479                 break;
6480         case 3:
6481                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6482                                          pinfo2, r->out.info, r->out.count);
6483                 break;
6484         default:
6485                 result = WERR_UNKNOWN_LEVEL;
6486                 break;
6487         }
6488
6489         SAFE_FREE(queue);
6490         TALLOC_FREE(pinfo2);
6491
6492         if (!W_ERROR_IS_OK(result)) {
6493                 return result;
6494         }
6495
6496         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6497                                                      spoolss_EnumJobs, 
6498                                                      *r->out.info, r->in.level,
6499                                                      *r->out.count);
6500         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6501         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6502
6503         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6504 }
6505
6506 /****************************************************************
6507  _spoolss_ScheduleJob
6508 ****************************************************************/
6509
6510 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6511                             struct spoolss_ScheduleJob *r)
6512 {
6513         return WERR_OK;
6514 }
6515
6516 /****************************************************************
6517 ****************************************************************/
6518
6519 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6520                                const char *printer_name,
6521                                uint32_t job_id,
6522                                struct spoolss_SetJobInfo1 *r)
6523 {
6524         char *old_doc_name;
6525
6526         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6527                 return WERR_BADFID;
6528         }
6529
6530         if (strequal(old_doc_name, r->document_name)) {
6531                 return WERR_OK;
6532         }
6533
6534         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6535                 return WERR_BADFID;
6536         }
6537
6538         return WERR_OK;
6539 }
6540
6541 /****************************************************************
6542  _spoolss_SetJob
6543 ****************************************************************/
6544
6545 WERROR _spoolss_SetJob(pipes_struct *p,
6546                        struct spoolss_SetJob *r)
6547 {
6548         int snum;
6549         WERROR errcode = WERR_BADFUNC;
6550
6551         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6552                 return WERR_BADFID;
6553         }
6554
6555         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6556                 return WERR_INVALID_PRINTER_NAME;
6557         }
6558
6559         switch (r->in.command) {
6560         case SPOOLSS_JOB_CONTROL_CANCEL:
6561         case SPOOLSS_JOB_CONTROL_DELETE:
6562                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6563                         errcode = WERR_OK;
6564                 }
6565                 break;
6566         case SPOOLSS_JOB_CONTROL_PAUSE:
6567                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6568                         errcode = WERR_OK;
6569                 }
6570                 break;
6571         case SPOOLSS_JOB_CONTROL_RESTART:
6572         case SPOOLSS_JOB_CONTROL_RESUME:
6573                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6574                         errcode = WERR_OK;
6575                 }
6576                 break;
6577         case 0:
6578                 errcode = WERR_OK;
6579                 break;
6580         default:
6581                 return WERR_UNKNOWN_LEVEL;
6582         }
6583
6584         if (!W_ERROR_IS_OK(errcode)) {
6585                 return errcode;
6586         }
6587
6588         if (r->in.ctr == NULL) {
6589                 return errcode;
6590         }
6591
6592         switch (r->in.ctr->level) {
6593         case 1:
6594                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6595                                            r->in.job_id,
6596                                            r->in.ctr->info.info1);
6597                 break;
6598         case 2:
6599         case 3:
6600         case 4:
6601         default:
6602                 return WERR_UNKNOWN_LEVEL;
6603         }
6604
6605         return errcode;
6606 }
6607
6608 /****************************************************************************
6609  Enumerates all printer drivers by level and architecture.
6610 ****************************************************************************/
6611
6612 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6613                                                        struct auth_serversupplied_info *server_info,
6614                                                        const char *servername,
6615                                                        const char *architecture,
6616                                                        uint32_t level,
6617                                                        union spoolss_DriverInfo **info_p,
6618                                                        uint32_t *count_p)
6619 {
6620         int i;
6621         uint32_t version;
6622         struct spoolss_DriverInfo8 *driver;
6623         union spoolss_DriverInfo *info = NULL;
6624         uint32_t count = 0;
6625         WERROR result = WERR_OK;
6626         uint32_t num_drivers;
6627         const char **drivers;
6628
6629         *count_p = 0;
6630         *info_p = NULL;
6631
6632         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6633                 result = winreg_get_driver_list(mem_ctx, server_info,
6634                                                 architecture, version,
6635                                                 &num_drivers, &drivers);
6636                 if (!W_ERROR_IS_OK(result)) {
6637                         goto out;
6638                 }
6639                 DEBUG(4, ("we have:[%d] drivers in environment"
6640                           " [%s] and version [%d]\n",
6641                           num_drivers, architecture, version));
6642
6643                 if (num_drivers != 0) {
6644                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6645                                                     union spoolss_DriverInfo,
6646                                                     count + num_drivers);
6647                         if (!info) {
6648                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6649                                         "failed to enlarge driver info buffer!\n"));
6650                                 result = WERR_NOMEM;
6651                                 goto out;
6652                         }
6653                 }
6654
6655                 for (i = 0; i < num_drivers; i++) {
6656                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6657
6658                         result = winreg_get_driver(mem_ctx, server_info,
6659                                                    architecture, drivers[i],
6660                                                    version, &driver);
6661                         if (!W_ERROR_IS_OK(result)) {
6662                                 goto out;
6663                         }
6664
6665                         switch (level) {
6666                         case 1:
6667                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6668                                                                    driver, servername);
6669                                 break;
6670                         case 2:
6671                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6672                                                                    driver, servername);
6673                                 break;
6674                         case 3:
6675                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6676                                                                    driver, servername);
6677                                 break;
6678                         case 4:
6679                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6680                                                                    driver, servername);
6681                                 break;
6682                         case 5:
6683                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6684                                                                    driver, servername);
6685                                 break;
6686                         case 6:
6687                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6688                                                                    driver, servername);
6689                                 break;
6690                         case 8:
6691                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6692                                                                    driver, servername);
6693                                 break;
6694                         default:
6695                                 result = WERR_UNKNOWN_LEVEL;
6696                                 break;
6697                         }
6698
6699                         TALLOC_FREE(driver);
6700
6701                         if (!W_ERROR_IS_OK(result)) {
6702                                 goto out;
6703                         }
6704                 }
6705
6706                 count += num_drivers;
6707                 TALLOC_FREE(drivers);
6708         }
6709
6710  out:
6711         TALLOC_FREE(drivers);
6712
6713         if (!W_ERROR_IS_OK(result)) {
6714                 TALLOC_FREE(info);
6715                 return result;
6716         }
6717
6718         *info_p = info;
6719         *count_p = count;
6720
6721         return WERR_OK;
6722 }
6723
6724 /****************************************************************************
6725  Enumerates all printer drivers by level.
6726 ****************************************************************************/
6727
6728 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6729                                        struct auth_serversupplied_info *server_info,
6730                                        const char *servername,
6731                                        const char *architecture,
6732                                        uint32_t level,
6733                                        union spoolss_DriverInfo **info_p,
6734                                        uint32_t *count_p)
6735 {
6736         uint32_t a,i;
6737         WERROR result = WERR_OK;
6738
6739         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6740
6741                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6742
6743                         union spoolss_DriverInfo *info = NULL;
6744                         uint32_t count = 0;
6745
6746                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6747                                                                           server_info,
6748                                                                           servername,
6749                                                                           archi_table[a].long_archi,
6750                                                                           level,
6751                                                                           &info,
6752                                                                           &count);
6753                         if (!W_ERROR_IS_OK(result)) {
6754                                 continue;
6755                         }
6756
6757                         for (i=0; i < count; i++) {
6758                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6759                                              info[i], info_p, count_p);
6760                         }
6761                 }
6762
6763                 return result;
6764         }
6765
6766         return enumprinterdrivers_level_by_architecture(mem_ctx,
6767                                                         server_info,
6768                                                         servername,
6769                                                         architecture,
6770                                                         level,
6771                                                         info_p,
6772                                                         count_p);
6773 }
6774
6775 /****************************************************************
6776  _spoolss_EnumPrinterDrivers
6777 ****************************************************************/
6778
6779 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6780                                    struct spoolss_EnumPrinterDrivers *r)
6781 {
6782         const char *cservername;
6783         WERROR result;
6784
6785         /* that's an [in out] buffer */
6786
6787         if (!r->in.buffer && (r->in.offered != 0)) {
6788                 return WERR_INVALID_PARAM;
6789         }
6790
6791         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6792
6793         *r->out.needed = 0;
6794         *r->out.count = 0;
6795         *r->out.info = NULL;
6796
6797         cservername = canon_servername(r->in.server);
6798
6799         if (!is_myname_or_ipaddr(cservername)) {
6800                 return WERR_UNKNOWN_PRINTER_DRIVER;
6801         }
6802
6803         result = enumprinterdrivers_level(p->mem_ctx,
6804                                           p->server_info,
6805                                           cservername,
6806                                           r->in.environment,
6807                                           r->in.level,
6808                                           r->out.info,
6809                                           r->out.count);
6810         if (!W_ERROR_IS_OK(result)) {
6811                 return result;
6812         }
6813
6814         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6815                                                      spoolss_EnumPrinterDrivers, 
6816                                                      *r->out.info, r->in.level,
6817                                                      *r->out.count);
6818         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6819         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6820
6821         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6822 }
6823
6824 /****************************************************************
6825  _spoolss_EnumForms
6826 ****************************************************************/
6827
6828 WERROR _spoolss_EnumForms(pipes_struct *p,
6829                           struct spoolss_EnumForms *r)
6830 {
6831         WERROR result;
6832
6833         *r->out.count = 0;
6834         *r->out.needed = 0;
6835         *r->out.info = NULL;
6836
6837         /* that's an [in out] buffer */
6838
6839         if (!r->in.buffer && (r->in.offered != 0) ) {
6840                 return WERR_INVALID_PARAM;
6841         }
6842
6843         DEBUG(4,("_spoolss_EnumForms\n"));
6844         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6845         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6846
6847         switch (r->in.level) {
6848         case 1:
6849                 result = winreg_printer_enumforms1(p->mem_ctx,
6850                                                    p->server_info,
6851                                                    r->out.count,
6852                                                    r->out.info);
6853                 break;
6854         default:
6855                 result = WERR_UNKNOWN_LEVEL;
6856                 break;
6857         }
6858
6859         if (!W_ERROR_IS_OK(result)) {
6860                 return result;
6861         }
6862
6863         if (*r->out.count == 0) {
6864                 return WERR_NO_MORE_ITEMS;
6865         }
6866
6867         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6868                                                      spoolss_EnumForms, 
6869                                                      *r->out.info, r->in.level,
6870                                                      *r->out.count);
6871         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6872         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6873
6874         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6875 }
6876
6877 /****************************************************************
6878  _spoolss_GetForm
6879 ****************************************************************/
6880
6881 WERROR _spoolss_GetForm(pipes_struct *p,
6882                         struct spoolss_GetForm *r)
6883 {
6884         WERROR result;
6885
6886         /* that's an [in out] buffer */
6887
6888         if (!r->in.buffer && (r->in.offered != 0)) {
6889                 return WERR_INVALID_PARAM;
6890         }
6891
6892         DEBUG(4,("_spoolss_GetForm\n"));
6893         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6894         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6895
6896         switch (r->in.level) {
6897         case 1:
6898                 result = winreg_printer_getform1(p->mem_ctx,
6899                                                  p->server_info,
6900                                                  r->in.form_name,
6901                                                  &r->out.info->info1);
6902                 break;
6903         default:
6904                 result = WERR_UNKNOWN_LEVEL;
6905                 break;
6906         }
6907
6908         if (!W_ERROR_IS_OK(result)) {
6909                 TALLOC_FREE(r->out.info);
6910                 return result;
6911         }
6912
6913         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6914                                                r->out.info, r->in.level);
6915         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6916
6917         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6918 }
6919
6920 /****************************************************************************
6921 ****************************************************************************/
6922
6923 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6924                           struct spoolss_PortInfo1 *r,
6925                           const char *name)
6926 {
6927         r->port_name = talloc_strdup(mem_ctx, name);
6928         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6929
6930         return WERR_OK;
6931 }
6932
6933 /****************************************************************************
6934  TODO: This probably needs distinguish between TCP/IP and Local ports
6935  somehow.
6936 ****************************************************************************/
6937
6938 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6939                           struct spoolss_PortInfo2 *r,
6940                           const char *name)
6941 {
6942         r->port_name = talloc_strdup(mem_ctx, name);
6943         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6944
6945         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6946         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6947
6948         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6949         W_ERROR_HAVE_NO_MEMORY(r->description);
6950
6951         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6952         r->reserved = 0;
6953
6954         return WERR_OK;
6955 }
6956
6957
6958 /****************************************************************************
6959  wrapper around the enumer ports command
6960 ****************************************************************************/
6961
6962 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6963 {
6964         char *cmd = lp_enumports_cmd();
6965         char **qlines = NULL;
6966         char *command = NULL;
6967         int numlines;
6968         int ret;
6969         int fd;
6970
6971         *count = 0;
6972         *lines = NULL;
6973
6974         /* if no hook then just fill in the default port */
6975
6976         if ( !*cmd ) {
6977                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6978                         return WERR_NOMEM;
6979                 }
6980                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6981                         TALLOC_FREE(qlines);
6982                         return WERR_NOMEM;
6983                 }
6984                 qlines[1] = NULL;
6985                 numlines = 1;
6986         }
6987         else {
6988                 /* we have a valid enumport command */
6989
6990                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6991                 if (!command) {
6992                         return WERR_NOMEM;
6993                 }
6994
6995                 DEBUG(10,("Running [%s]\n", command));
6996                 ret = smbrun(command, &fd);
6997                 DEBUG(10,("Returned [%d]\n", ret));
6998                 TALLOC_FREE(command);
6999                 if (ret != 0) {
7000                         if (fd != -1) {
7001                                 close(fd);
7002                         }
7003                         return WERR_ACCESS_DENIED;
7004                 }
7005
7006                 numlines = 0;
7007                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7008                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7009                 close(fd);
7010         }
7011
7012         *count = numlines;
7013         *lines = qlines;
7014
7015         return WERR_OK;
7016 }
7017
7018 /****************************************************************************
7019  enumports level 1.
7020 ****************************************************************************/
7021
7022 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7023                                 union spoolss_PortInfo **info_p,
7024                                 uint32_t *count)
7025 {
7026         union spoolss_PortInfo *info = NULL;
7027         int i=0;
7028         WERROR result = WERR_OK;
7029         char **qlines = NULL;
7030         int numlines = 0;
7031
7032         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7033         if (!W_ERROR_IS_OK(result)) {
7034                 goto out;
7035         }
7036
7037         if (numlines) {
7038                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7039                 if (!info) {
7040                         DEBUG(10,("Returning WERR_NOMEM\n"));
7041                         result = WERR_NOMEM;
7042                         goto out;
7043                 }
7044
7045                 for (i=0; i<numlines; i++) {
7046                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7047                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7048                         if (!W_ERROR_IS_OK(result)) {
7049                                 goto out;
7050                         }
7051                 }
7052         }
7053         TALLOC_FREE(qlines);
7054
7055 out:
7056         if (!W_ERROR_IS_OK(result)) {
7057                 TALLOC_FREE(info);
7058                 TALLOC_FREE(qlines);
7059                 *count = 0;
7060                 *info_p = NULL;
7061                 return result;
7062         }
7063
7064         *info_p = info;
7065         *count = numlines;
7066
7067         return WERR_OK;
7068 }
7069
7070 /****************************************************************************
7071  enumports level 2.
7072 ****************************************************************************/
7073
7074 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7075                                 union spoolss_PortInfo **info_p,
7076                                 uint32_t *count)
7077 {
7078         union spoolss_PortInfo *info = NULL;
7079         int i=0;
7080         WERROR result = WERR_OK;
7081         char **qlines = NULL;
7082         int numlines = 0;
7083
7084         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7085         if (!W_ERROR_IS_OK(result)) {
7086                 goto out;
7087         }
7088
7089         if (numlines) {
7090                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7091                 if (!info) {
7092                         DEBUG(10,("Returning WERR_NOMEM\n"));
7093                         result = WERR_NOMEM;
7094                         goto out;
7095                 }
7096
7097                 for (i=0; i<numlines; i++) {
7098                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7099                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7100                         if (!W_ERROR_IS_OK(result)) {
7101                                 goto out;
7102                         }
7103                 }
7104         }
7105         TALLOC_FREE(qlines);
7106
7107 out:
7108         if (!W_ERROR_IS_OK(result)) {
7109                 TALLOC_FREE(info);
7110                 TALLOC_FREE(qlines);
7111                 *count = 0;
7112                 *info_p = NULL;
7113                 return result;
7114         }
7115
7116         *info_p = info;
7117         *count = numlines;
7118
7119         return WERR_OK;
7120 }
7121
7122 /****************************************************************
7123  _spoolss_EnumPorts
7124 ****************************************************************/
7125
7126 WERROR _spoolss_EnumPorts(pipes_struct *p,
7127                           struct spoolss_EnumPorts *r)
7128 {
7129         WERROR result;
7130
7131         /* that's an [in out] buffer */
7132
7133         if (!r->in.buffer && (r->in.offered != 0)) {
7134                 return WERR_INVALID_PARAM;
7135         }
7136
7137         DEBUG(4,("_spoolss_EnumPorts\n"));
7138
7139         *r->out.count = 0;
7140         *r->out.needed = 0;
7141         *r->out.info = NULL;
7142
7143         switch (r->in.level) {
7144         case 1:
7145                 result = enumports_level_1(p->mem_ctx, r->out.info,
7146                                            r->out.count);
7147                 break;
7148         case 2:
7149                 result = enumports_level_2(p->mem_ctx, r->out.info,
7150                                            r->out.count);
7151                 break;
7152         default:
7153                 return WERR_UNKNOWN_LEVEL;
7154         }
7155
7156         if (!W_ERROR_IS_OK(result)) {
7157                 return result;
7158         }
7159
7160         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7161                                                      spoolss_EnumPorts, 
7162                                                      *r->out.info, r->in.level,
7163                                                      *r->out.count);
7164         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7165         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7166
7167         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7168 }
7169
7170 /****************************************************************************
7171 ****************************************************************************/
7172
7173 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7174                                            const char *server,
7175                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7176                                            struct spoolss_DeviceMode *devmode,
7177                                            struct security_descriptor *secdesc,
7178                                            struct spoolss_UserLevelCtr *user_ctr,
7179                                            struct policy_handle *handle)
7180 {
7181         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7182         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7183         int     snum;
7184         WERROR err = WERR_OK;
7185
7186         /* samba does not have a concept of local, non-shared printers yet, so
7187          * make sure we always setup sharename - gd */
7188         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7189             (info2->printername != NULL && info2->printername[0] != '\0')) {
7190                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7191                         "no sharename has been set, setting printername %s as sharename\n",
7192                         info2->printername));
7193                 info2->sharename = info2->printername;
7194         }
7195
7196         /* check to see if the printer already exists */
7197         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7198                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7199                         info2->sharename));
7200                 return WERR_PRINTER_ALREADY_EXISTS;
7201         }
7202
7203         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7204                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7205                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7206                                 info2->printername));
7207                         return WERR_PRINTER_ALREADY_EXISTS;
7208                 }
7209         }
7210
7211         /* validate printer info struct */
7212         if (!info2->printername || strlen(info2->printername) == 0) {
7213                 return WERR_INVALID_PRINTER_NAME;
7214         }
7215         if (!info2->portname || strlen(info2->portname) == 0) {
7216                 return WERR_UNKNOWN_PORT;
7217         }
7218         if (!info2->drivername || strlen(info2->drivername) == 0) {
7219                 return WERR_UNKNOWN_PRINTER_DRIVER;
7220         }
7221         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7222                 return WERR_UNKNOWN_PRINTPROCESSOR;
7223         }
7224
7225         /* FIXME!!!  smbd should check to see if the driver is installed before
7226            trying to add a printer like this  --jerry */
7227
7228         if (*lp_addprinter_cmd() ) {
7229                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7230                                        info2) ) {
7231                         return WERR_ACCESS_DENIED;
7232                 }
7233         } else {
7234                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7235                         "smb.conf parameter \"addprinter command\" is defined. This"
7236                         "parameter must exist for this call to succeed\n",
7237                         info2->sharename ));
7238         }
7239
7240         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7241                 return WERR_ACCESS_DENIED;
7242         }
7243
7244         /* you must be a printer admin to add a new printer */
7245         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7246                 return WERR_ACCESS_DENIED;
7247         }
7248
7249         /*
7250          * Do sanity check on the requested changes for Samba.
7251          */
7252
7253         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7254                 return WERR_INVALID_PARAM;
7255         }
7256
7257         if (devmode == NULL) {
7258                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7259         }
7260
7261         update_dsspooler(p->mem_ctx,
7262                          p->server_info,
7263                          0,
7264                          info2,
7265                          NULL);
7266
7267         err = winreg_update_printer(p->mem_ctx,
7268                                     p->server_info,
7269                                     info2->sharename,
7270                                     info2_mask,
7271                                     info2,
7272                                     devmode,
7273                                     secdesc);
7274         if (!W_ERROR_IS_OK(err)) {
7275                 return err;
7276         }
7277
7278         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7279                 /* Handle open failed - remove addition. */
7280                 ZERO_STRUCTP(handle);
7281                 return WERR_ACCESS_DENIED;
7282         }
7283
7284         return WERR_OK;
7285 }
7286
7287 /****************************************************************
7288  _spoolss_AddPrinterEx
7289 ****************************************************************/
7290
7291 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7292                              struct spoolss_AddPrinterEx *r)
7293 {
7294         switch (r->in.info_ctr->level) {
7295         case 1:
7296                 /* we don't handle yet */
7297                 /* but I know what to do ... */
7298                 return WERR_UNKNOWN_LEVEL;
7299         case 2:
7300                 return spoolss_addprinterex_level_2(p, r->in.server,
7301                                                     r->in.info_ctr,
7302                                                     r->in.devmode_ctr->devmode,
7303                                                     r->in.secdesc_ctr->sd,
7304                                                     r->in.userlevel_ctr,
7305                                                     r->out.handle);
7306         default:
7307                 return WERR_UNKNOWN_LEVEL;
7308         }
7309 }
7310
7311 /****************************************************************
7312  _spoolss_AddPrinter
7313 ****************************************************************/
7314
7315 WERROR _spoolss_AddPrinter(pipes_struct *p,
7316                            struct spoolss_AddPrinter *r)
7317 {
7318         struct spoolss_AddPrinterEx a;
7319         struct spoolss_UserLevelCtr userlevel_ctr;
7320
7321         ZERO_STRUCT(userlevel_ctr);
7322
7323         userlevel_ctr.level = 1;
7324
7325         a.in.server             = r->in.server;
7326         a.in.info_ctr           = r->in.info_ctr;
7327         a.in.devmode_ctr        = r->in.devmode_ctr;
7328         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7329         a.in.userlevel_ctr      = &userlevel_ctr;
7330         a.out.handle            = r->out.handle;
7331
7332         return _spoolss_AddPrinterEx(p, &a);
7333 }
7334
7335 /****************************************************************
7336  _spoolss_AddPrinterDriverEx
7337 ****************************************************************/
7338
7339 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7340                                    struct spoolss_AddPrinterDriverEx *r)
7341 {
7342         WERROR err = WERR_OK;
7343         const char *driver_name = NULL;
7344         uint32_t version;
7345         const char *fn;
7346
7347         switch (p->opnum) {
7348                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7349                         fn = "_spoolss_AddPrinterDriver";
7350                         break;
7351                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7352                         fn = "_spoolss_AddPrinterDriverEx";
7353                         break;
7354                 default:
7355                         return WERR_INVALID_PARAM;
7356         }
7357
7358         /*
7359          * we only support the semantics of AddPrinterDriver()
7360          * i.e. only copy files that are newer than existing ones
7361          */
7362
7363         if (r->in.flags == 0) {
7364                 return WERR_INVALID_PARAM;
7365         }
7366
7367         if (r->in.flags != APD_COPY_NEW_FILES) {
7368                 return WERR_ACCESS_DENIED;
7369         }
7370
7371         /* FIXME */
7372         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7373                 /* Clever hack from Martin Zielinski <mz@seh.de>
7374                  * to allow downgrade from level 8 (Vista).
7375                  */
7376                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7377                         r->in.info_ctr->level));
7378                 return WERR_UNKNOWN_LEVEL;
7379         }
7380
7381         DEBUG(5,("Cleaning driver's information\n"));
7382         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7383         if (!W_ERROR_IS_OK(err))
7384                 goto done;
7385
7386         DEBUG(5,("Moving driver to final destination\n"));
7387         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7388                                                               &err)) ) {
7389                 goto done;
7390         }
7391
7392         err = winreg_add_driver(p->mem_ctx, p->server_info,
7393                                 r->in.info_ctr, &driver_name, &version);
7394         if (!W_ERROR_IS_OK(err)) {
7395                 goto done;
7396         }
7397
7398         /*
7399          * I think this is where he DrvUpgradePrinter() hook would be
7400          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7401          * server.  Right now, we just need to send ourselves a message
7402          * to update each printer bound to this driver.   --jerry
7403          */
7404
7405         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7406                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7407                         fn, driver_name));
7408         }
7409
7410 done:
7411         return err;
7412 }
7413
7414 /****************************************************************
7415  _spoolss_AddPrinterDriver
7416 ****************************************************************/
7417
7418 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7419                                  struct spoolss_AddPrinterDriver *r)
7420 {
7421         struct spoolss_AddPrinterDriverEx a;
7422
7423         switch (r->in.info_ctr->level) {
7424         case 2:
7425         case 3:
7426         case 4:
7427         case 5:
7428                 break;
7429         default:
7430                 return WERR_UNKNOWN_LEVEL;
7431         }
7432
7433         a.in.servername         = r->in.servername;
7434         a.in.info_ctr           = r->in.info_ctr;
7435         a.in.flags              = APD_COPY_NEW_FILES;
7436
7437         return _spoolss_AddPrinterDriverEx(p, &a);
7438 }
7439
7440 /****************************************************************************
7441 ****************************************************************************/
7442
7443 struct _spoolss_paths {
7444         int type;
7445         const char *share;
7446         const char *dir;
7447 };
7448
7449 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7450
7451 static const struct _spoolss_paths spoolss_paths[]= {
7452         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7453         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7454 };
7455
7456 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7457                                           const char *servername,
7458                                           const char *environment,
7459                                           int component,
7460                                           char **path)
7461 {
7462         const char *pservername = NULL;
7463         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7464         const char *short_archi;
7465
7466         *path = NULL;
7467
7468         /* environment may be empty */
7469         if (environment && strlen(environment)) {
7470                 long_archi = environment;
7471         }
7472
7473         /* servername may be empty */
7474         if (servername && strlen(servername)) {
7475                 pservername = canon_servername(servername);
7476
7477                 if (!is_myname_or_ipaddr(pservername)) {
7478                         return WERR_INVALID_PARAM;
7479                 }
7480         }
7481
7482         if (!(short_archi = get_short_archi(long_archi))) {
7483                 return WERR_INVALID_ENVIRONMENT;
7484         }
7485
7486         switch (component) {
7487         case SPOOLSS_PRTPROCS_PATH:
7488         case SPOOLSS_DRIVER_PATH:
7489                 if (pservername) {
7490                         *path = talloc_asprintf(mem_ctx,
7491                                         "\\\\%s\\%s\\%s",
7492                                         pservername,
7493                                         spoolss_paths[component].share,
7494                                         short_archi);
7495                 } else {
7496                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7497                                         SPOOLSS_DEFAULT_SERVER_PATH,
7498                                         spoolss_paths[component].dir,
7499                                         short_archi);
7500                 }
7501                 break;
7502         default:
7503                 return WERR_INVALID_PARAM;
7504         }
7505
7506         if (!*path) {
7507                 return WERR_NOMEM;
7508         }
7509
7510         return WERR_OK;
7511 }
7512
7513 /****************************************************************************
7514 ****************************************************************************/
7515
7516 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7517                                           const char *servername,
7518                                           const char *environment,
7519                                           struct spoolss_DriverDirectoryInfo1 *r)
7520 {
7521         WERROR werr;
7522         char *path = NULL;
7523
7524         werr = compose_spoolss_server_path(mem_ctx,
7525                                            servername,
7526                                            environment,
7527                                            SPOOLSS_DRIVER_PATH,
7528                                            &path);
7529         if (!W_ERROR_IS_OK(werr)) {
7530                 return werr;
7531         }
7532
7533         DEBUG(4,("printer driver directory: [%s]\n", path));
7534
7535         r->directory_name = path;
7536
7537         return WERR_OK;
7538 }
7539
7540 /****************************************************************
7541  _spoolss_GetPrinterDriverDirectory
7542 ****************************************************************/
7543
7544 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7545                                           struct spoolss_GetPrinterDriverDirectory *r)
7546 {
7547         WERROR werror;
7548
7549         /* that's an [in out] buffer */
7550
7551         if (!r->in.buffer && (r->in.offered != 0)) {
7552                 return WERR_INVALID_PARAM;
7553         }
7554
7555         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7556                 r->in.level));
7557
7558         *r->out.needed = 0;
7559
7560         /* r->in.level is ignored */
7561
7562         werror = getprinterdriverdir_level_1(p->mem_ctx,
7563                                              r->in.server,
7564                                              r->in.environment,
7565                                              &r->out.info->info1);
7566         if (!W_ERROR_IS_OK(werror)) {
7567                 TALLOC_FREE(r->out.info);
7568                 return werror;
7569         }
7570
7571         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7572                                                r->out.info, r->in.level);
7573         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7574
7575         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7576 }
7577
7578 /****************************************************************
7579  _spoolss_EnumPrinterData
7580 ****************************************************************/
7581
7582 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7583                                 struct spoolss_EnumPrinterData *r)
7584 {
7585         WERROR result;
7586         struct spoolss_EnumPrinterDataEx r2;
7587         uint32_t count;
7588         struct spoolss_PrinterEnumValues *info, *val = NULL;
7589         uint32_t needed;
7590
7591         r2.in.handle    = r->in.handle;
7592         r2.in.key_name  = "PrinterDriverData";
7593         r2.in.offered   = 0;
7594         r2.out.count    = &count;
7595         r2.out.info     = &info;
7596         r2.out.needed   = &needed;
7597
7598         result = _spoolss_EnumPrinterDataEx(p, &r2);
7599         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7600                 r2.in.offered = needed;
7601                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7602         }
7603         if (!W_ERROR_IS_OK(result)) {
7604                 return result;
7605         }
7606
7607         /*
7608          * The NT machine wants to know the biggest size of value and data
7609          *
7610          * cf: MSDN EnumPrinterData remark section
7611          */
7612
7613         if (!r->in.value_offered && !r->in.data_offered) {
7614                 uint32_t biggest_valuesize = 0;
7615                 uint32_t biggest_datasize = 0;
7616                 int i, name_length;
7617
7618                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7619
7620                 for (i=0; i<count; i++) {
7621
7622                         name_length = strlen(info[i].value_name);
7623                         if (strlen(info[i].value_name) > biggest_valuesize) {
7624                                 biggest_valuesize = name_length;
7625                         }
7626
7627                         if (info[i].data_length > biggest_datasize) {
7628                                 biggest_datasize = info[i].data_length;
7629                         }
7630
7631                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7632                                 biggest_datasize));
7633                 }
7634
7635                 /* the value is an UNICODE string but real_value_size is the length
7636                    in bytes including the trailing 0 */
7637
7638                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7639                 *r->out.data_needed  = biggest_datasize;
7640
7641                 DEBUG(6,("final values: [%d], [%d]\n",
7642                         *r->out.value_needed, *r->out.data_needed));
7643
7644                 return WERR_OK;
7645         }
7646
7647         if (r->in.enum_index < count) {
7648                 val = &info[r->in.enum_index];
7649         }
7650
7651         if (val == NULL) {
7652                 /* out_value should default to "" or else NT4 has
7653                    problems unmarshalling the response */
7654
7655                 if (r->in.value_offered) {
7656                         *r->out.value_needed = 1;
7657                         r->out.value_name = talloc_strdup(r, "");
7658                         if (!r->out.value_name) {
7659                                 return WERR_NOMEM;
7660                         }
7661                 } else {
7662                         r->out.value_name = NULL;
7663                         *r->out.value_needed = 0;
7664                 }
7665
7666                 /* the data is counted in bytes */
7667
7668                 *r->out.data_needed = r->in.data_offered;
7669
7670                 result = WERR_NO_MORE_ITEMS;
7671         } else {
7672                 /*
7673                  * the value is:
7674                  * - counted in bytes in the request
7675                  * - counted in UNICODE chars in the max reply
7676                  * - counted in bytes in the real size
7677                  *
7678                  * take a pause *before* coding not *during* coding
7679                  */
7680
7681                 /* name */
7682                 if (r->in.value_offered) {
7683                         r->out.value_name = talloc_strdup(r, val->value_name);
7684                         if (!r->out.value_name) {
7685                                 return WERR_NOMEM;
7686                         }
7687                         *r->out.value_needed = val->value_name_len;
7688                 } else {
7689                         r->out.value_name = NULL;
7690                         *r->out.value_needed = 0;
7691                 }
7692
7693                 /* type */
7694
7695                 *r->out.type = val->type;
7696
7697                 /* data - counted in bytes */
7698
7699                 /*
7700                  * See the section "Dynamically Typed Query Parameters"
7701                  * in MS-RPRN.
7702                  */
7703
7704                 if (r->out.data && val->data && val->data->data &&
7705                                 val->data_length && r->in.data_offered) {
7706                         memcpy(r->out.data, val->data->data,
7707                                 MIN(val->data_length,r->in.data_offered));
7708                 }
7709
7710                 *r->out.data_needed = val->data_length;
7711
7712                 result = WERR_OK;
7713         }
7714
7715         return result;
7716 }
7717
7718 /****************************************************************
7719  _spoolss_SetPrinterData
7720 ****************************************************************/
7721
7722 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7723                                struct spoolss_SetPrinterData *r)
7724 {
7725         struct spoolss_SetPrinterDataEx r2;
7726
7727         r2.in.handle            = r->in.handle;
7728         r2.in.key_name          = "PrinterDriverData";
7729         r2.in.value_name        = r->in.value_name;
7730         r2.in.type              = r->in.type;
7731         r2.in.data              = r->in.data;
7732         r2.in.offered           = r->in.offered;
7733
7734         return _spoolss_SetPrinterDataEx(p, &r2);
7735 }
7736
7737 /****************************************************************
7738  _spoolss_ResetPrinter
7739 ****************************************************************/
7740
7741 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7742                              struct spoolss_ResetPrinter *r)
7743 {
7744         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7745         int             snum;
7746
7747         DEBUG(5,("_spoolss_ResetPrinter\n"));
7748
7749         /*
7750          * All we do is to check to see if the handle and queue is valid.
7751          * This call really doesn't mean anything to us because we only
7752          * support RAW printing.   --jerry
7753          */
7754
7755         if (!Printer) {
7756                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7757                         OUR_HANDLE(r->in.handle)));
7758                 return WERR_BADFID;
7759         }
7760
7761         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7762                 return WERR_BADFID;
7763
7764
7765         /* blindly return success */
7766         return WERR_OK;
7767 }
7768
7769 /****************************************************************
7770  _spoolss_DeletePrinterData
7771 ****************************************************************/
7772
7773 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7774                                   struct spoolss_DeletePrinterData *r)
7775 {
7776         struct spoolss_DeletePrinterDataEx r2;
7777
7778         r2.in.handle            = r->in.handle;
7779         r2.in.key_name          = "PrinterDriverData";
7780         r2.in.value_name        = r->in.value_name;
7781
7782         return _spoolss_DeletePrinterDataEx(p, &r2);
7783 }
7784
7785 /****************************************************************
7786  _spoolss_AddForm
7787 ****************************************************************/
7788
7789 WERROR _spoolss_AddForm(pipes_struct *p,
7790                         struct spoolss_AddForm *r)
7791 {
7792         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7793         int snum = -1;
7794         WERROR status = WERR_OK;
7795         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7796
7797         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7798
7799         DEBUG(5,("_spoolss_AddForm\n"));
7800
7801         if (!Printer) {
7802                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7803                         OUR_HANDLE(r->in.handle)));
7804                 return WERR_BADFID;
7805         }
7806
7807         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7808            and not a printer admin, then fail */
7809
7810         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7811              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7812              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7813                                           p->server_info->info3->base.domain.string,
7814                                           NULL,
7815                                           p->server_info->ptok,
7816                                           lp_printer_admin(snum))) {
7817                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7818                 return WERR_ACCESS_DENIED;
7819         }
7820
7821         switch (form->flags) {
7822         case SPOOLSS_FORM_USER:
7823         case SPOOLSS_FORM_BUILTIN:
7824         case SPOOLSS_FORM_PRINTER:
7825                 break;
7826         default:
7827                 return WERR_INVALID_PARAM;
7828         }
7829
7830         status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7831         if (!W_ERROR_IS_OK(status)) {
7832                 return status;
7833         }
7834
7835         /*
7836          * ChangeID must always be set if this is a printer
7837          */
7838         if (Printer->printer_type == SPLHND_PRINTER) {
7839                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7840                         return WERR_BADFID;
7841                 }
7842
7843                 status = winreg_printer_update_changeid(p->mem_ctx,
7844                                                         p->server_info,
7845                                                         lp_const_servicename(snum));
7846                 if (!W_ERROR_IS_OK(status)) {
7847                         return status;
7848                 }
7849         }
7850
7851         return status;
7852 }
7853
7854 /****************************************************************
7855  _spoolss_DeleteForm
7856 ****************************************************************/
7857
7858 WERROR _spoolss_DeleteForm(pipes_struct *p,
7859                            struct spoolss_DeleteForm *r)
7860 {
7861         const char *form_name = r->in.form_name;
7862         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7863         int snum = -1;
7864         WERROR status = WERR_OK;
7865         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7866
7867         DEBUG(5,("_spoolss_DeleteForm\n"));
7868
7869         if (!Printer) {
7870                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7871                         OUR_HANDLE(r->in.handle)));
7872                 return WERR_BADFID;
7873         }
7874
7875         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7876              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7877              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7878                                           p->server_info->info3->base.domain.string,
7879                                           NULL,
7880                                           p->server_info->ptok,
7881                                           lp_printer_admin(snum))) {
7882                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7883                 return WERR_ACCESS_DENIED;
7884         }
7885
7886         status = winreg_printer_deleteform1(p->mem_ctx,
7887                                             p->server_info,
7888                                             form_name);
7889         if (!W_ERROR_IS_OK(status)) {
7890                 return status;
7891         }
7892
7893         /*
7894          * ChangeID must always be set if this is a printer
7895          */
7896         if (Printer->printer_type == SPLHND_PRINTER) {
7897                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7898                         return WERR_BADFID;
7899                 }
7900
7901                 status = winreg_printer_update_changeid(p->mem_ctx,
7902                                                         p->server_info,
7903                                                         lp_const_servicename(snum));
7904                 if (!W_ERROR_IS_OK(status)) {
7905                         return status;
7906                 }
7907         }
7908
7909         return status;
7910 }
7911
7912 /****************************************************************
7913  _spoolss_SetForm
7914 ****************************************************************/
7915
7916 WERROR _spoolss_SetForm(pipes_struct *p,
7917                         struct spoolss_SetForm *r)
7918 {
7919         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7920         const char *form_name = r->in.form_name;
7921         int snum = -1;
7922         WERROR status = WERR_OK;
7923         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7924
7925         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7926
7927         DEBUG(5,("_spoolss_SetForm\n"));
7928
7929         if (!Printer) {
7930                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7931                         OUR_HANDLE(r->in.handle)));
7932                 return WERR_BADFID;
7933         }
7934
7935         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7936            and not a printer admin, then fail */
7937
7938         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7939              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7940              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7941                                           p->server_info->info3->base.domain.string,
7942                                           NULL,
7943                                           p->server_info->ptok,
7944                                           lp_printer_admin(snum))) {
7945                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7946                 return WERR_ACCESS_DENIED;
7947         }
7948
7949         status = winreg_printer_setform1(p->mem_ctx,
7950                                          p->server_info,
7951                                          form_name,
7952                                          form);
7953         if (!W_ERROR_IS_OK(status)) {
7954                 return status;
7955         }
7956
7957         /*
7958          * ChangeID must always be set if this is a printer
7959          */
7960         if (Printer->printer_type == SPLHND_PRINTER) {
7961                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7962                         return WERR_BADFID;
7963                 }
7964
7965                 status = winreg_printer_update_changeid(p->mem_ctx,
7966                                                         p->server_info,
7967                                                         lp_const_servicename(snum));
7968                 if (!W_ERROR_IS_OK(status)) {
7969                         return status;
7970                 }
7971         }
7972
7973         return status;
7974 }
7975
7976 /****************************************************************************
7977  fill_print_processor1
7978 ****************************************************************************/
7979
7980 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7981                                     struct spoolss_PrintProcessorInfo1 *r,
7982                                     const char *print_processor_name)
7983 {
7984         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7985         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7986
7987         return WERR_OK;
7988 }
7989
7990 /****************************************************************************
7991  enumprintprocessors level 1.
7992 ****************************************************************************/
7993
7994 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7995                                           union spoolss_PrintProcessorInfo **info_p,
7996                                           uint32_t *count)
7997 {
7998         union spoolss_PrintProcessorInfo *info;
7999         WERROR result;
8000
8001         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8002         W_ERROR_HAVE_NO_MEMORY(info);
8003
8004         *count = 1;
8005
8006         result = fill_print_processor1(info, &info[0].info1, "winprint");
8007         if (!W_ERROR_IS_OK(result)) {
8008                 goto out;
8009         }
8010
8011  out:
8012         if (!W_ERROR_IS_OK(result)) {
8013                 TALLOC_FREE(info);
8014                 *count = 0;
8015                 return result;
8016         }
8017
8018         *info_p = info;
8019
8020         return WERR_OK;
8021 }
8022
8023 /****************************************************************
8024  _spoolss_EnumPrintProcessors
8025 ****************************************************************/
8026
8027 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8028                                     struct spoolss_EnumPrintProcessors *r)
8029 {
8030         WERROR result;
8031
8032         /* that's an [in out] buffer */
8033
8034         if (!r->in.buffer && (r->in.offered != 0)) {
8035                 return WERR_INVALID_PARAM;
8036         }
8037
8038         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8039
8040         /*
8041          * Enumerate the print processors ...
8042          *
8043          * Just reply with "winprint", to keep NT happy
8044          * and I can use my nice printer checker.
8045          */
8046
8047         *r->out.count = 0;
8048         *r->out.needed = 0;
8049         *r->out.info = NULL;
8050
8051         switch (r->in.level) {
8052         case 1:
8053                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8054                                                      r->out.count);
8055                 break;
8056         default:
8057                 return WERR_UNKNOWN_LEVEL;
8058         }
8059
8060         if (!W_ERROR_IS_OK(result)) {
8061                 return result;
8062         }
8063
8064         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8065                                                      spoolss_EnumPrintProcessors,
8066                                                      *r->out.info, r->in.level,
8067                                                      *r->out.count);
8068         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8069         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8070
8071         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8072 }
8073
8074 /****************************************************************************
8075  fill_printprocdatatype1
8076 ****************************************************************************/
8077
8078 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8079                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8080                                       const char *name_array)
8081 {
8082         r->name_array = talloc_strdup(mem_ctx, name_array);
8083         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8084
8085         return WERR_OK;
8086 }
8087
8088 /****************************************************************************
8089  enumprintprocdatatypes level 1.
8090 ****************************************************************************/
8091
8092 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8093                                              union spoolss_PrintProcDataTypesInfo **info_p,
8094                                              uint32_t *count)
8095 {
8096         WERROR result;
8097         union spoolss_PrintProcDataTypesInfo *info;
8098
8099         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8100         W_ERROR_HAVE_NO_MEMORY(info);
8101
8102         *count = 1;
8103
8104         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8105         if (!W_ERROR_IS_OK(result)) {
8106                 goto out;
8107         }
8108
8109  out:
8110         if (!W_ERROR_IS_OK(result)) {
8111                 TALLOC_FREE(info);
8112                 *count = 0;
8113                 return result;
8114         }
8115
8116         *info_p = info;
8117
8118         return WERR_OK;
8119 }
8120
8121 /****************************************************************
8122  _spoolss_EnumPrintProcDataTypes
8123 ****************************************************************/
8124
8125 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8126                                        struct spoolss_EnumPrintProcDataTypes *r)
8127 {
8128         WERROR result;
8129
8130         /* that's an [in out] buffer */
8131
8132         if (!r->in.buffer && (r->in.offered != 0)) {
8133                 return WERR_INVALID_PARAM;
8134         }
8135
8136         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8137
8138         *r->out.count = 0;
8139         *r->out.needed = 0;
8140         *r->out.info = NULL;
8141
8142         switch (r->in.level) {
8143         case 1:
8144                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8145                                                         r->out.count);
8146                 break;
8147         default:
8148                 return WERR_UNKNOWN_LEVEL;
8149         }
8150
8151         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8152                                                      spoolss_EnumPrintProcDataTypes, 
8153                                                      *r->out.info, r->in.level,
8154                                                      *r->out.count);
8155         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8156         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8157
8158         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8159 }
8160
8161 /****************************************************************************
8162  fill_monitor_1
8163 ****************************************************************************/
8164
8165 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8166                              struct spoolss_MonitorInfo1 *r,
8167                              const char *monitor_name)
8168 {
8169         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8170         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8171
8172         return WERR_OK;
8173 }
8174
8175 /****************************************************************************
8176  fill_monitor_2
8177 ****************************************************************************/
8178
8179 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8180                              struct spoolss_MonitorInfo2 *r,
8181                              const char *monitor_name,
8182                              const char *environment,
8183                              const char *dll_name)
8184 {
8185         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8186         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8187         r->environment                  = talloc_strdup(mem_ctx, environment);
8188         W_ERROR_HAVE_NO_MEMORY(r->environment);
8189         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8190         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8191
8192         return WERR_OK;
8193 }
8194
8195 /****************************************************************************
8196  enumprintmonitors level 1.
8197 ****************************************************************************/
8198
8199 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8200                                         union spoolss_MonitorInfo **info_p,
8201                                         uint32_t *count)
8202 {
8203         union spoolss_MonitorInfo *info;
8204         WERROR result = WERR_OK;
8205
8206         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8207         W_ERROR_HAVE_NO_MEMORY(info);
8208
8209         *count = 2;
8210
8211         result = fill_monitor_1(info, &info[0].info1,
8212                                 SPL_LOCAL_PORT);
8213         if (!W_ERROR_IS_OK(result)) {
8214                 goto out;
8215         }
8216
8217         result = fill_monitor_1(info, &info[1].info1,
8218                                 SPL_TCPIP_PORT);
8219         if (!W_ERROR_IS_OK(result)) {
8220                 goto out;
8221         }
8222
8223 out:
8224         if (!W_ERROR_IS_OK(result)) {
8225                 TALLOC_FREE(info);
8226                 *count = 0;
8227                 return result;
8228         }
8229
8230         *info_p = info;
8231
8232         return WERR_OK;
8233 }
8234
8235 /****************************************************************************
8236  enumprintmonitors level 2.
8237 ****************************************************************************/
8238
8239 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8240                                         union spoolss_MonitorInfo **info_p,
8241                                         uint32_t *count)
8242 {
8243         union spoolss_MonitorInfo *info;
8244         WERROR result = WERR_OK;
8245
8246         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8247         W_ERROR_HAVE_NO_MEMORY(info);
8248
8249         *count = 2;
8250
8251         result = fill_monitor_2(info, &info[0].info2,
8252                                 SPL_LOCAL_PORT,
8253                                 "Windows NT X86", /* FIXME */
8254                                 "localmon.dll");
8255         if (!W_ERROR_IS_OK(result)) {
8256                 goto out;
8257         }
8258
8259         result = fill_monitor_2(info, &info[1].info2,
8260                                 SPL_TCPIP_PORT,
8261                                 "Windows NT X86", /* FIXME */
8262                                 "tcpmon.dll");
8263         if (!W_ERROR_IS_OK(result)) {
8264                 goto out;
8265         }
8266
8267 out:
8268         if (!W_ERROR_IS_OK(result)) {
8269                 TALLOC_FREE(info);
8270                 *count = 0;
8271                 return result;
8272         }
8273
8274         *info_p = info;
8275
8276         return WERR_OK;
8277 }
8278
8279 /****************************************************************
8280  _spoolss_EnumMonitors
8281 ****************************************************************/
8282
8283 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8284                              struct spoolss_EnumMonitors *r)
8285 {
8286         WERROR result;
8287
8288         /* that's an [in out] buffer */
8289
8290         if (!r->in.buffer && (r->in.offered != 0)) {
8291                 return WERR_INVALID_PARAM;
8292         }
8293
8294         DEBUG(5,("_spoolss_EnumMonitors\n"));
8295
8296         /*
8297          * Enumerate the print monitors ...
8298          *
8299          * Just reply with "Local Port", to keep NT happy
8300          * and I can use my nice printer checker.
8301          */
8302
8303         *r->out.count = 0;
8304         *r->out.needed = 0;
8305         *r->out.info = NULL;
8306
8307         switch (r->in.level) {
8308         case 1:
8309                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8310                                                    r->out.count);
8311                 break;
8312         case 2:
8313                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8314                                                    r->out.count);
8315                 break;
8316         default:
8317                 return WERR_UNKNOWN_LEVEL;
8318         }
8319
8320         if (!W_ERROR_IS_OK(result)) {
8321                 return result;
8322         }
8323
8324         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8325                                                      spoolss_EnumMonitors, 
8326                                                      *r->out.info, r->in.level,
8327                                                      *r->out.count);
8328         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8329         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8330
8331         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8332 }
8333
8334 /****************************************************************************
8335 ****************************************************************************/
8336
8337 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8338                              const print_queue_struct *queue,
8339                              int count, int snum,
8340                              struct spoolss_PrinterInfo2 *pinfo2,
8341                              uint32_t jobid,
8342                              struct spoolss_JobInfo1 *r)
8343 {
8344         int i = 0;
8345         bool found = false;
8346
8347         for (i=0; i<count; i++) {
8348                 if (queue[i].job == (int)jobid) {
8349                         found = true;
8350                         break;
8351                 }
8352         }
8353
8354         if (found == false) {
8355                 /* NT treats not found as bad param... yet another bad choice */
8356                 return WERR_INVALID_PARAM;
8357         }
8358
8359         return fill_job_info1(mem_ctx,
8360                               r,
8361                               &queue[i],
8362                               i,
8363                               snum,
8364                               pinfo2);
8365 }
8366
8367 /****************************************************************************
8368 ****************************************************************************/
8369
8370 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8371                              const print_queue_struct *queue,
8372                              int count, int snum,
8373                              struct spoolss_PrinterInfo2 *pinfo2,
8374                              uint32_t jobid,
8375                              struct spoolss_JobInfo2 *r)
8376 {
8377         int i = 0;
8378         bool found = false;
8379         struct spoolss_DeviceMode *devmode;
8380         WERROR result;
8381
8382         for (i=0; i<count; i++) {
8383                 if (queue[i].job == (int)jobid) {
8384                         found = true;
8385                         break;
8386                 }
8387         }
8388
8389         if (found == false) {
8390                 /* NT treats not found as bad param... yet another bad
8391                    choice */
8392                 return WERR_INVALID_PARAM;
8393         }
8394
8395         /*
8396          * if the print job does not have a DEVMODE associated with it,
8397          * just use the one for the printer. A NULL devicemode is not
8398          *  a failure condition
8399          */
8400
8401         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8402         if (!devmode) {
8403                 result = spoolss_create_default_devmode(mem_ctx,
8404                                                 pinfo2->printername,
8405                                                 &devmode);
8406                 if (!W_ERROR_IS_OK(result)) {
8407                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8408                         return result;
8409                 }
8410         }
8411
8412         return fill_job_info2(mem_ctx,
8413                               r,
8414                               &queue[i],
8415                               i,
8416                               snum,
8417                               pinfo2,
8418                               devmode);
8419 }
8420
8421 /****************************************************************
8422  _spoolss_GetJob
8423 ****************************************************************/
8424
8425 WERROR _spoolss_GetJob(pipes_struct *p,
8426                        struct spoolss_GetJob *r)
8427 {
8428         WERROR result = WERR_OK;
8429         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8430         int snum;
8431         int count;
8432         print_queue_struct      *queue = NULL;
8433         print_status_struct prt_status;
8434
8435         /* that's an [in out] buffer */
8436
8437         if (!r->in.buffer && (r->in.offered != 0)) {
8438                 return WERR_INVALID_PARAM;
8439         }
8440
8441         DEBUG(5,("_spoolss_GetJob\n"));
8442
8443         *r->out.needed = 0;
8444
8445         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8446                 return WERR_BADFID;
8447         }
8448
8449         result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
8450                                     lp_servicename(snum), &pinfo2);
8451         if (!W_ERROR_IS_OK(result)) {
8452                 return result;
8453         }
8454
8455         count = print_queue_status(snum, &queue, &prt_status);
8456
8457         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8458                      count, prt_status.status, prt_status.message));
8459
8460         switch (r->in.level) {
8461         case 1:
8462                 result = getjob_level_1(p->mem_ctx,
8463                                         queue, count, snum, pinfo2,
8464                                         r->in.job_id, &r->out.info->info1);
8465                 break;
8466         case 2:
8467                 result = getjob_level_2(p->mem_ctx,
8468                                         queue, count, snum, pinfo2,
8469                                         r->in.job_id, &r->out.info->info2);
8470                 break;
8471         default:
8472                 result = WERR_UNKNOWN_LEVEL;
8473                 break;
8474         }
8475
8476         SAFE_FREE(queue);
8477         TALLOC_FREE(pinfo2);
8478
8479         if (!W_ERROR_IS_OK(result)) {
8480                 TALLOC_FREE(r->out.info);
8481                 return result;
8482         }
8483
8484         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8485                                                                                    r->in.level);
8486         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8487
8488         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8489 }
8490
8491 /****************************************************************
8492  _spoolss_GetPrinterDataEx
8493 ****************************************************************/
8494
8495 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8496                                  struct spoolss_GetPrinterDataEx *r)
8497 {
8498
8499         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8500         const char *printer;
8501         int                     snum = 0;
8502         WERROR result = WERR_OK;
8503         DATA_BLOB blob;
8504         enum winreg_Type val_type;
8505         uint8_t *val_data;
8506         uint32_t val_size;
8507
8508
8509         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8510
8511         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8512                 r->in.key_name, r->in.value_name));
8513
8514         /* in case of problem, return some default values */
8515
8516         *r->out.needed  = 0;
8517         *r->out.type    = REG_NONE;
8518
8519         if (!Printer) {
8520                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8521                         OUR_HANDLE(r->in.handle)));
8522                 result = WERR_BADFID;
8523                 goto done;
8524         }
8525
8526         /* Is the handle to a printer or to the server? */
8527
8528         if (Printer->printer_type == SPLHND_SERVER) {
8529
8530                 union spoolss_PrinterData data;
8531
8532                 result = getprinterdata_printer_server(p->mem_ctx,
8533                                                        r->in.value_name,
8534                                                        r->out.type,
8535                                                        &data);
8536                 if (!W_ERROR_IS_OK(result)) {
8537                         return result;
8538                 }
8539
8540                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8541                                                   *r->out.type, &data);
8542                 if (!W_ERROR_IS_OK(result)) {
8543                         return result;
8544                 }
8545
8546                 *r->out.needed = blob.length;
8547
8548                 if (r->in.offered >= *r->out.needed) {
8549                         memcpy(r->out.data, blob.data, blob.length);
8550                 }
8551
8552                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8553         }
8554
8555         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8556                 return WERR_BADFID;
8557         }
8558         printer = lp_const_servicename(snum);
8559
8560         /* check to see if the keyname is valid */
8561         if (!strlen(r->in.key_name)) {
8562                 return WERR_INVALID_PARAM;
8563         }
8564
8565         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8566         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8567             strequal(r->in.value_name, "ChangeId")) {
8568                 *r->out.type = REG_DWORD;
8569                 *r->out.needed = 4;
8570                 if (r->in.offered >= *r->out.needed) {
8571                         uint32_t changeid = 0;
8572
8573                         result = winreg_printer_get_changeid(p->mem_ctx,
8574                                                              p->server_info,
8575                                                              printer,
8576                                                              &changeid);
8577                         if (!W_ERROR_IS_OK(result)) {
8578                                 return result;
8579                         }
8580
8581                         SIVAL(r->out.data, 0, changeid);
8582                         result = WERR_OK;
8583                 }
8584                 goto done;
8585         }
8586
8587         result = winreg_get_printer_dataex(p->mem_ctx,
8588                                            p->server_info,
8589                                            printer,
8590                                            r->in.key_name,
8591                                            r->in.value_name,
8592                                            &val_type,
8593                                            &val_data,
8594                                            &val_size);
8595         if (!W_ERROR_IS_OK(result)) {
8596                 return result;
8597         }
8598
8599         *r->out.needed = val_size;
8600         *r->out.type = val_type;
8601
8602         if (r->in.offered >= *r->out.needed) {
8603                 memcpy(r->out.data, val_data, val_size);
8604         }
8605
8606  done:
8607         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8608         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8609
8610         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8611 }
8612
8613 /****************************************************************
8614  _spoolss_SetPrinterDataEx
8615 ****************************************************************/
8616
8617 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8618                                  struct spoolss_SetPrinterDataEx *r)
8619 {
8620         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8621         int                     snum = 0;
8622         WERROR                  result = WERR_OK;
8623         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8624         char                    *oid_string;
8625
8626         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8627
8628         /* From MSDN documentation of SetPrinterDataEx: pass request to
8629            SetPrinterData if key is "PrinterDriverData" */
8630
8631         if (!Printer) {
8632                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8633                         OUR_HANDLE(r->in.handle)));
8634                 return WERR_BADFID;
8635         }
8636
8637         if (Printer->printer_type == SPLHND_SERVER) {
8638                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8639                         "Not implemented for server handles yet\n"));
8640                 return WERR_INVALID_PARAM;
8641         }
8642
8643         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8644                 return WERR_BADFID;
8645         }
8646
8647         /*
8648          * Access check : NT returns "access denied" if you make a
8649          * SetPrinterData call without the necessary privildge.
8650          * we were originally returning OK if nothing changed
8651          * which made Win2k issue **a lot** of SetPrinterData
8652          * when connecting to a printer  --jerry
8653          */
8654
8655         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8656                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8657                         "change denied by handle access permissions\n"));
8658                 return WERR_ACCESS_DENIED;
8659         }
8660
8661         result = winreg_get_printer(Printer, p->server_info,
8662                                     Printer->servername,
8663                                     lp_servicename(snum),
8664                                     &pinfo2);
8665         if (!W_ERROR_IS_OK(result)) {
8666                 return result;
8667         }
8668
8669         /* check for OID in valuename */
8670
8671         oid_string = strchr(r->in.value_name, ',');
8672         if (oid_string) {
8673                 *oid_string = '\0';
8674                 oid_string++;
8675         }
8676
8677         /* save the registry data */
8678
8679         result = winreg_set_printer_dataex(p->mem_ctx,
8680                                            p->server_info,
8681                                            pinfo2->sharename,
8682                                            r->in.key_name,
8683                                            r->in.value_name,
8684                                            r->in.type,
8685                                            r->in.data,
8686                                            r->in.offered);
8687
8688         if (W_ERROR_IS_OK(result)) {
8689                 /* save the OID if one was specified */
8690                 if (oid_string) {
8691                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8692                                 r->in.key_name, SPOOL_OID_KEY);
8693                         if (!str) {
8694                                 result = WERR_NOMEM;
8695                                 goto done;
8696                         }
8697
8698                         /*
8699                          * I'm not checking the status here on purpose.  Don't know
8700                          * if this is right, but I'm returning the status from the
8701                          * previous set_printer_dataex() call.  I have no idea if
8702                          * this is right.    --jerry
8703                          */
8704                         winreg_set_printer_dataex(p->mem_ctx,
8705                                                   p->server_info,
8706                                                   pinfo2->sharename,
8707                                                   str,
8708                                                   r->in.value_name,
8709                                                   REG_SZ,
8710                                                   (uint8_t *) oid_string,
8711                                                   strlen(oid_string) + 1);
8712                 }
8713
8714                 result = winreg_printer_update_changeid(p->mem_ctx,
8715                                                         p->server_info,
8716                                                         lp_const_servicename(snum));
8717
8718         }
8719
8720 done:
8721         talloc_free(pinfo2);
8722         return result;
8723 }
8724
8725 /****************************************************************
8726  _spoolss_DeletePrinterDataEx
8727 ****************************************************************/
8728
8729 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8730                                     struct spoolss_DeletePrinterDataEx *r)
8731 {
8732         const char *printer;
8733         int             snum=0;
8734         WERROR          status = WERR_OK;
8735         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8736
8737         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8738
8739         if (!Printer) {
8740                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8741                         "Invalid handle (%s:%u:%u).\n",
8742                         OUR_HANDLE(r->in.handle)));
8743                 return WERR_BADFID;
8744         }
8745
8746         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8747                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8748                         "printer properties change denied by handle\n"));
8749                 return WERR_ACCESS_DENIED;
8750         }
8751
8752         if (!r->in.value_name || !r->in.key_name) {
8753                 return WERR_NOMEM;
8754         }
8755
8756         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8757                 return WERR_BADFID;
8758         }
8759         printer = lp_const_servicename(snum);
8760
8761         status = winreg_delete_printer_dataex(p->mem_ctx,
8762                                               p->server_info,
8763                                               printer,
8764                                               r->in.key_name,
8765                                               r->in.value_name);
8766         if (W_ERROR_IS_OK(status)) {
8767                 status = winreg_printer_update_changeid(p->mem_ctx,
8768                                                         p->server_info,
8769                                                         printer);
8770         }
8771
8772         return status;
8773 }
8774
8775 /****************************************************************
8776  _spoolss_EnumPrinterKey
8777 ****************************************************************/
8778
8779 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8780                                struct spoolss_EnumPrinterKey *r)
8781 {
8782         uint32_t        num_keys;
8783         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8784         int             snum = 0;
8785         WERROR          result = WERR_BADFILE;
8786         const char **array = NULL;
8787         DATA_BLOB blob;
8788
8789         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8790
8791         if (!Printer) {
8792                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8793                         OUR_HANDLE(r->in.handle)));
8794                 return WERR_BADFID;
8795         }
8796
8797         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8798                 return WERR_BADFID;
8799         }
8800
8801         result = winreg_enum_printer_key(p->mem_ctx,
8802                                          p->server_info,
8803                                          lp_const_servicename(snum),
8804                                          r->in.key_name,
8805                                          &num_keys,
8806                                          &array);
8807         if (!W_ERROR_IS_OK(result)) {
8808                 goto done;
8809         }
8810
8811         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8812                 result = WERR_NOMEM;
8813                 goto done;
8814         }
8815
8816         *r->out._ndr_size = r->in.offered / 2;
8817         *r->out.needed = blob.length;
8818
8819         if (r->in.offered < *r->out.needed) {
8820                 result = WERR_MORE_DATA;
8821         } else {
8822                 result = WERR_OK;
8823                 r->out.key_buffer->string_array = array;
8824         }
8825
8826  done:
8827         if (!W_ERROR_IS_OK(result)) {
8828                 TALLOC_FREE(array);
8829                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8830                         *r->out.needed = 0;
8831                 }
8832         }
8833
8834         return result;
8835 }
8836
8837 /****************************************************************
8838  _spoolss_DeletePrinterKey
8839 ****************************************************************/
8840
8841 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8842                                  struct spoolss_DeletePrinterKey *r)
8843 {
8844         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8845         int                     snum=0;
8846         WERROR                  status;
8847         const char *printer;
8848
8849         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8850
8851         if (!Printer) {
8852                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8853                         OUR_HANDLE(r->in.handle)));
8854                 return WERR_BADFID;
8855         }
8856
8857         /* if keyname == NULL, return error */
8858         if ( !r->in.key_name )
8859                 return WERR_INVALID_PARAM;
8860
8861         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8862                 return WERR_BADFID;
8863         }
8864
8865         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8866                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8867                         "printer properties change denied by handle\n"));
8868                 return WERR_ACCESS_DENIED;
8869         }
8870
8871         printer = lp_const_servicename(snum);
8872
8873         /* delete the key and all subkeys */
8874         status = winreg_delete_printer_key(p->mem_ctx,
8875                                            p->server_info,
8876                                            printer,
8877                                            r->in.key_name);
8878         if (W_ERROR_IS_OK(status)) {
8879                 status = winreg_printer_update_changeid(p->mem_ctx,
8880                                                         p->server_info,
8881                                                         printer);
8882         }
8883
8884         return status;
8885 }
8886
8887 /****************************************************************
8888  _spoolss_EnumPrinterDataEx
8889 ****************************************************************/
8890
8891 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8892                                   struct spoolss_EnumPrinterDataEx *r)
8893 {
8894         uint32_t        count = 0;
8895         struct spoolss_PrinterEnumValues *info = NULL;
8896         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8897         int             snum;
8898         WERROR          result;
8899
8900         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8901
8902         *r->out.count = 0;
8903         *r->out.needed = 0;
8904         *r->out.info = NULL;
8905
8906         if (!Printer) {
8907                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8908                         OUR_HANDLE(r->in.handle)));
8909                 return WERR_BADFID;
8910         }
8911
8912         /*
8913          * first check for a keyname of NULL or "".  Win2k seems to send
8914          * this a lot and we should send back WERR_INVALID_PARAM
8915          * no need to spend time looking up the printer in this case.
8916          * --jerry
8917          */
8918
8919         if (!strlen(r->in.key_name)) {
8920                 result = WERR_INVALID_PARAM;
8921                 goto done;
8922         }
8923
8924         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8925                 return WERR_BADFID;
8926         }
8927
8928         /* now look for a match on the key name */
8929         result = winreg_enum_printer_dataex(p->mem_ctx,
8930                                             p->server_info,
8931                                             lp_const_servicename(snum),
8932                                             r->in.key_name,
8933                                             &count,
8934                                             &info);
8935         if (!W_ERROR_IS_OK(result)) {
8936                 goto done;
8937         }
8938
8939 #if 0 /* FIXME - gd */
8940         /* housekeeping information in the reply */
8941
8942         /* Fix from Martin Zielinski <mz@seh.de> - ensure
8943          * the hand marshalled container size is a multiple
8944          * of 4 bytes for RPC alignment.
8945          */
8946
8947         if (needed % 4) {
8948                 needed += 4-(needed % 4);
8949         }
8950 #endif
8951         *r->out.count   = count;
8952         *r->out.info    = info;
8953
8954  done:
8955         if (!W_ERROR_IS_OK(result)) {
8956                 return result;
8957         }
8958
8959         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8960                                                spoolss_EnumPrinterDataEx, 
8961                                                *r->out.info,
8962                                                *r->out.count);
8963         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8964         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8965
8966         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8967 }
8968
8969 /****************************************************************************
8970 ****************************************************************************/
8971
8972 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8973                                                  const char *servername,
8974                                                  const char *environment,
8975                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
8976 {
8977         WERROR werr;
8978         char *path = NULL;
8979
8980         werr = compose_spoolss_server_path(mem_ctx,
8981                                            servername,
8982                                            environment,
8983                                            SPOOLSS_PRTPROCS_PATH,
8984                                            &path);
8985         if (!W_ERROR_IS_OK(werr)) {
8986                 return werr;
8987         }
8988
8989         DEBUG(4,("print processor directory: [%s]\n", path));
8990
8991         r->directory_name = path;
8992
8993         return WERR_OK;
8994 }
8995
8996 /****************************************************************
8997  _spoolss_GetPrintProcessorDirectory
8998 ****************************************************************/
8999
9000 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9001                                            struct spoolss_GetPrintProcessorDirectory *r)
9002 {
9003         WERROR result;
9004
9005         /* that's an [in out] buffer */
9006
9007         if (!r->in.buffer && (r->in.offered != 0)) {
9008                 return WERR_INVALID_PARAM;
9009         }
9010
9011         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9012                 r->in.level));
9013
9014         *r->out.needed = 0;
9015
9016         /* r->in.level is ignored */
9017
9018         /* We always should reply with a local print processor directory so that
9019          * users are not forced to have a [prnproc$] share on the Samba spoolss
9020          * server - Guenther */
9021
9022         result = getprintprocessordirectory_level_1(p->mem_ctx,
9023                                                     NULL, /* r->in.server */
9024                                                     r->in.environment,
9025                                                     &r->out.info->info1);
9026         if (!W_ERROR_IS_OK(result)) {
9027                 TALLOC_FREE(r->out.info);
9028                 return result;
9029         }
9030
9031         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9032                                                                                    r->out.info, r->in.level);
9033         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9034
9035         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9036 }
9037
9038 /*******************************************************************
9039  ********************************************************************/
9040
9041 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9042                                const char *dllname)
9043 {
9044         enum ndr_err_code ndr_err;
9045         struct spoolss_MonitorUi ui;
9046
9047         ui.dll_name = dllname;
9048
9049         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9050                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9051         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9052                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9053         }
9054         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9055 }
9056
9057 /*******************************************************************
9058  Streams the monitor UI DLL name in UNICODE
9059 *******************************************************************/
9060
9061 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9062                                NT_USER_TOKEN *token, DATA_BLOB *in,
9063                                DATA_BLOB *out, uint32_t *needed)
9064 {
9065         const char *dllname = "tcpmonui.dll";
9066
9067         *needed = (strlen(dllname)+1) * 2;
9068
9069         if (out->length < *needed) {
9070                 return WERR_INSUFFICIENT_BUFFER;
9071         }
9072
9073         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9074                 return WERR_NOMEM;
9075         }
9076
9077         return WERR_OK;
9078 }
9079
9080 /*******************************************************************
9081  ********************************************************************/
9082
9083 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9084                              struct spoolss_PortData1 *port1,
9085                              const DATA_BLOB *buf)
9086 {
9087         enum ndr_err_code ndr_err;
9088         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9089                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9090         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9091                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9092         }
9093         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9094 }
9095
9096 /*******************************************************************
9097  ********************************************************************/
9098
9099 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9100                              struct spoolss_PortData2 *port2,
9101                              const DATA_BLOB *buf)
9102 {
9103         enum ndr_err_code ndr_err;
9104         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9105                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9106         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9107                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9108         }
9109         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9110 }
9111
9112 /*******************************************************************
9113  Create a new TCP/IP port
9114 *******************************************************************/
9115
9116 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9117                              NT_USER_TOKEN *token, DATA_BLOB *in,
9118                              DATA_BLOB *out, uint32_t *needed)
9119 {
9120         struct spoolss_PortData1 port1;
9121         struct spoolss_PortData2 port2;
9122         char *device_uri = NULL;
9123         uint32_t version;
9124
9125         const char *portname;
9126         const char *hostaddress;
9127         const char *queue;
9128         uint32_t port_number;
9129         uint32_t protocol;
9130
9131         /* peek for spoolss_PortData version */
9132
9133         if (!in || (in->length < (128 + 4))) {
9134                 return WERR_GENERAL_FAILURE;
9135         }
9136
9137         version = IVAL(in->data, 128);
9138
9139         switch (version) {
9140                 case 1:
9141                         ZERO_STRUCT(port1);
9142
9143                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9144                                 return WERR_NOMEM;
9145                         }
9146
9147                         portname        = port1.portname;
9148                         hostaddress     = port1.hostaddress;
9149                         queue           = port1.queue;
9150                         protocol        = port1.protocol;
9151                         port_number     = port1.port_number;
9152
9153                         break;
9154                 case 2:
9155                         ZERO_STRUCT(port2);
9156
9157                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9158                                 return WERR_NOMEM;
9159                         }
9160
9161                         portname        = port2.portname;
9162                         hostaddress     = port2.hostaddress;
9163                         queue           = port2.queue;
9164                         protocol        = port2.protocol;
9165                         port_number     = port2.port_number;
9166
9167                         break;
9168                 default:
9169                         DEBUG(1,("xcvtcp_addport: "
9170                                 "unknown version of port_data: %d\n", version));
9171                         return WERR_UNKNOWN_PORT;
9172         }
9173
9174         /* create the device URI and call the add_port_hook() */
9175
9176         switch (protocol) {
9177         case PROTOCOL_RAWTCP_TYPE:
9178                 device_uri = talloc_asprintf(mem_ctx,
9179                                 "socket://%s:%d/", hostaddress,
9180                                 port_number);
9181                 break;
9182
9183         case PROTOCOL_LPR_TYPE:
9184                 device_uri = talloc_asprintf(mem_ctx,
9185                         "lpr://%s/%s", hostaddress, queue );
9186                 break;
9187
9188         default:
9189                 return WERR_UNKNOWN_PORT;
9190         }
9191
9192         if (!device_uri) {
9193                 return WERR_NOMEM;
9194         }
9195
9196         return add_port_hook(mem_ctx, token, portname, device_uri);
9197 }
9198
9199 /*******************************************************************
9200 *******************************************************************/
9201
9202 struct xcv_api_table xcvtcp_cmds[] = {
9203         { "MonitorUI",  xcvtcp_monitorui },
9204         { "AddPort",    xcvtcp_addport},
9205         { NULL,         NULL }
9206 };
9207
9208 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9209                                      NT_USER_TOKEN *token, const char *command,
9210                                      DATA_BLOB *inbuf,
9211                                      DATA_BLOB *outbuf,
9212                                      uint32_t *needed )
9213 {
9214         int i;
9215
9216         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9217
9218         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9219                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9220                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9221         }
9222
9223         return WERR_BADFUNC;
9224 }
9225
9226 /*******************************************************************
9227 *******************************************************************/
9228 #if 0   /* don't support management using the "Local Port" monitor */
9229
9230 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9231                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9232                                  DATA_BLOB *out, uint32_t *needed)
9233 {
9234         const char *dllname = "localui.dll";
9235
9236         *needed = (strlen(dllname)+1) * 2;
9237
9238         if (out->length < *needed) {
9239                 return WERR_INSUFFICIENT_BUFFER;
9240         }
9241
9242         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9243                 return WERR_NOMEM;
9244         }
9245
9246         return WERR_OK;
9247 }
9248
9249 /*******************************************************************
9250 *******************************************************************/
9251
9252 struct xcv_api_table xcvlocal_cmds[] = {
9253         { "MonitorUI",  xcvlocal_monitorui },
9254         { NULL,         NULL }
9255 };
9256 #else
9257 struct xcv_api_table xcvlocal_cmds[] = {
9258         { NULL,         NULL }
9259 };
9260 #endif
9261
9262
9263
9264 /*******************************************************************
9265 *******************************************************************/
9266
9267 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9268                                        NT_USER_TOKEN *token, const char *command,
9269                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9270                                        uint32_t *needed)
9271 {
9272         int i;
9273
9274         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9275
9276         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9277                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9278                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9279         }
9280         return WERR_BADFUNC;
9281 }
9282
9283 /****************************************************************
9284  _spoolss_XcvData
9285 ****************************************************************/
9286
9287 WERROR _spoolss_XcvData(pipes_struct *p,
9288                         struct spoolss_XcvData *r)
9289 {
9290         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9291         DATA_BLOB out_data = data_blob_null;
9292         WERROR werror;
9293
9294         if (!Printer) {
9295                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9296                         OUR_HANDLE(r->in.handle)));
9297                 return WERR_BADFID;
9298         }
9299
9300         /* Has to be a handle to the TCP/IP port monitor */
9301
9302         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9303                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9304                 return WERR_BADFID;
9305         }
9306
9307         /* requires administrative access to the server */
9308
9309         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9310                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9311                 return WERR_ACCESS_DENIED;
9312         }
9313
9314         /* Allocate the outgoing buffer */
9315
9316         if (r->in.out_data_size) {
9317                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9318                 if (out_data.data == NULL) {
9319                         return WERR_NOMEM;
9320                 }
9321         }
9322
9323         switch ( Printer->printer_type ) {
9324         case SPLHND_PORTMON_TCP:
9325                 werror = process_xcvtcp_command(p->mem_ctx,
9326                                                 p->server_info->ptok,
9327                                                 r->in.function_name,
9328                                                 &r->in.in_data, &out_data,
9329                                                 r->out.needed);
9330                 break;
9331         case SPLHND_PORTMON_LOCAL:
9332                 werror = process_xcvlocal_command(p->mem_ctx,
9333                                                   p->server_info->ptok,
9334                                                   r->in.function_name,
9335                                                   &r->in.in_data, &out_data,
9336                                                   r->out.needed);
9337                 break;
9338         default:
9339                 werror = WERR_INVALID_PRINT_MONITOR;
9340         }
9341
9342         if (!W_ERROR_IS_OK(werror)) {
9343                 return werror;
9344         }
9345
9346         *r->out.status_code = 0;
9347
9348         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9349                 memcpy(r->out.out_data, out_data.data,
9350                         MIN(r->in.out_data_size, out_data.length));
9351         }
9352
9353         return WERR_OK;
9354 }
9355
9356 /****************************************************************
9357  _spoolss_AddPrintProcessor
9358 ****************************************************************/
9359
9360 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9361                                   struct spoolss_AddPrintProcessor *r)
9362 {
9363         /* for now, just indicate success and ignore the add.  We'll
9364            automatically set the winprint processor for printer
9365            entries later.  Used to debug the LexMark Optra S 1855 PCL
9366            driver --jerry */
9367
9368         return WERR_OK;
9369 }
9370
9371 /****************************************************************
9372  _spoolss_AddPort
9373 ****************************************************************/
9374
9375 WERROR _spoolss_AddPort(pipes_struct *p,
9376                         struct spoolss_AddPort *r)
9377 {
9378         /* do what w2k3 does */
9379
9380         return WERR_NOT_SUPPORTED;
9381 }
9382
9383 /****************************************************************
9384  _spoolss_GetPrinterDriver
9385 ****************************************************************/
9386
9387 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9388                                  struct spoolss_GetPrinterDriver *r)
9389 {
9390         p->rng_fault_state = true;
9391         return WERR_NOT_SUPPORTED;
9392 }
9393
9394 /****************************************************************
9395  _spoolss_ReadPrinter
9396 ****************************************************************/
9397
9398 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9399                             struct spoolss_ReadPrinter *r)
9400 {
9401         p->rng_fault_state = true;
9402         return WERR_NOT_SUPPORTED;
9403 }
9404
9405 /****************************************************************
9406  _spoolss_WaitForPrinterChange
9407 ****************************************************************/
9408
9409 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9410                                      struct spoolss_WaitForPrinterChange *r)
9411 {
9412         p->rng_fault_state = true;
9413         return WERR_NOT_SUPPORTED;
9414 }
9415
9416 /****************************************************************
9417  _spoolss_ConfigurePort
9418 ****************************************************************/
9419
9420 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9421                               struct spoolss_ConfigurePort *r)
9422 {
9423         p->rng_fault_state = true;
9424         return WERR_NOT_SUPPORTED;
9425 }
9426
9427 /****************************************************************
9428  _spoolss_DeletePort
9429 ****************************************************************/
9430
9431 WERROR _spoolss_DeletePort(pipes_struct *p,
9432                            struct spoolss_DeletePort *r)
9433 {
9434         p->rng_fault_state = true;
9435         return WERR_NOT_SUPPORTED;
9436 }
9437
9438 /****************************************************************
9439  _spoolss_CreatePrinterIC
9440 ****************************************************************/
9441
9442 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9443                                 struct spoolss_CreatePrinterIC *r)
9444 {
9445         p->rng_fault_state = true;
9446         return WERR_NOT_SUPPORTED;
9447 }
9448
9449 /****************************************************************
9450  _spoolss_PlayGDIScriptOnPrinterIC
9451 ****************************************************************/
9452
9453 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9454                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9455 {
9456         p->rng_fault_state = true;
9457         return WERR_NOT_SUPPORTED;
9458 }
9459
9460 /****************************************************************
9461  _spoolss_DeletePrinterIC
9462 ****************************************************************/
9463
9464 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9465                                 struct spoolss_DeletePrinterIC *r)
9466 {
9467         p->rng_fault_state = true;
9468         return WERR_NOT_SUPPORTED;
9469 }
9470
9471 /****************************************************************
9472  _spoolss_AddPrinterConnection
9473 ****************************************************************/
9474
9475 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9476                                      struct spoolss_AddPrinterConnection *r)
9477 {
9478         p->rng_fault_state = true;
9479         return WERR_NOT_SUPPORTED;
9480 }
9481
9482 /****************************************************************
9483  _spoolss_DeletePrinterConnection
9484 ****************************************************************/
9485
9486 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9487                                         struct spoolss_DeletePrinterConnection *r)
9488 {
9489         p->rng_fault_state = true;
9490         return WERR_NOT_SUPPORTED;
9491 }
9492
9493 /****************************************************************
9494  _spoolss_PrinterMessageBox
9495 ****************************************************************/
9496
9497 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9498                                   struct spoolss_PrinterMessageBox *r)
9499 {
9500         p->rng_fault_state = true;
9501         return WERR_NOT_SUPPORTED;
9502 }
9503
9504 /****************************************************************
9505  _spoolss_AddMonitor
9506 ****************************************************************/
9507
9508 WERROR _spoolss_AddMonitor(pipes_struct *p,
9509                            struct spoolss_AddMonitor *r)
9510 {
9511         p->rng_fault_state = true;
9512         return WERR_NOT_SUPPORTED;
9513 }
9514
9515 /****************************************************************
9516  _spoolss_DeleteMonitor
9517 ****************************************************************/
9518
9519 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9520                               struct spoolss_DeleteMonitor *r)
9521 {
9522         p->rng_fault_state = true;
9523         return WERR_NOT_SUPPORTED;
9524 }
9525
9526 /****************************************************************
9527  _spoolss_DeletePrintProcessor
9528 ****************************************************************/
9529
9530 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9531                                      struct spoolss_DeletePrintProcessor *r)
9532 {
9533         p->rng_fault_state = true;
9534         return WERR_NOT_SUPPORTED;
9535 }
9536
9537 /****************************************************************
9538  _spoolss_AddPrintProvidor
9539 ****************************************************************/
9540
9541 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9542                                  struct spoolss_AddPrintProvidor *r)
9543 {
9544         p->rng_fault_state = true;
9545         return WERR_NOT_SUPPORTED;
9546 }
9547
9548 /****************************************************************
9549  _spoolss_DeletePrintProvidor
9550 ****************************************************************/
9551
9552 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9553                                     struct spoolss_DeletePrintProvidor *r)
9554 {
9555         p->rng_fault_state = true;
9556         return WERR_NOT_SUPPORTED;
9557 }
9558
9559 /****************************************************************
9560  _spoolss_FindFirstPrinterChangeNotification
9561 ****************************************************************/
9562
9563 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9564                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9565 {
9566         p->rng_fault_state = true;
9567         return WERR_NOT_SUPPORTED;
9568 }
9569
9570 /****************************************************************
9571  _spoolss_FindNextPrinterChangeNotification
9572 ****************************************************************/
9573
9574 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9575                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9576 {
9577         p->rng_fault_state = true;
9578         return WERR_NOT_SUPPORTED;
9579 }
9580
9581 /****************************************************************
9582  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9583 ****************************************************************/
9584
9585 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9586                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9587 {
9588         p->rng_fault_state = true;
9589         return WERR_NOT_SUPPORTED;
9590 }
9591
9592 /****************************************************************
9593  _spoolss_ReplyOpenPrinter
9594 ****************************************************************/
9595
9596 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9597                                  struct spoolss_ReplyOpenPrinter *r)
9598 {
9599         p->rng_fault_state = true;
9600         return WERR_NOT_SUPPORTED;
9601 }
9602
9603 /****************************************************************
9604  _spoolss_RouterReplyPrinter
9605 ****************************************************************/
9606
9607 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9608                                    struct spoolss_RouterReplyPrinter *r)
9609 {
9610         p->rng_fault_state = true;
9611         return WERR_NOT_SUPPORTED;
9612 }
9613
9614 /****************************************************************
9615  _spoolss_ReplyClosePrinter
9616 ****************************************************************/
9617
9618 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9619                                   struct spoolss_ReplyClosePrinter *r)
9620 {
9621         p->rng_fault_state = true;
9622         return WERR_NOT_SUPPORTED;
9623 }
9624
9625 /****************************************************************
9626  _spoolss_AddPortEx
9627 ****************************************************************/
9628
9629 WERROR _spoolss_AddPortEx(pipes_struct *p,
9630                           struct spoolss_AddPortEx *r)
9631 {
9632         p->rng_fault_state = true;
9633         return WERR_NOT_SUPPORTED;
9634 }
9635
9636 /****************************************************************
9637  _spoolss_RouterFindFirstPrinterChangeNotification
9638 ****************************************************************/
9639
9640 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9641                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9642 {
9643         p->rng_fault_state = true;
9644         return WERR_NOT_SUPPORTED;
9645 }
9646
9647 /****************************************************************
9648  _spoolss_SpoolerInit
9649 ****************************************************************/
9650
9651 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9652                             struct spoolss_SpoolerInit *r)
9653 {
9654         p->rng_fault_state = true;
9655         return WERR_NOT_SUPPORTED;
9656 }
9657
9658 /****************************************************************
9659  _spoolss_ResetPrinterEx
9660 ****************************************************************/
9661
9662 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9663                                struct spoolss_ResetPrinterEx *r)
9664 {
9665         p->rng_fault_state = true;
9666         return WERR_NOT_SUPPORTED;
9667 }
9668
9669 /****************************************************************
9670  _spoolss_RouterReplyPrinterEx
9671 ****************************************************************/
9672
9673 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9674                                      struct spoolss_RouterReplyPrinterEx *r)
9675 {
9676         p->rng_fault_state = true;
9677         return WERR_NOT_SUPPORTED;
9678 }
9679
9680 /****************************************************************
9681  _spoolss_44
9682 ****************************************************************/
9683
9684 WERROR _spoolss_44(pipes_struct *p,
9685                    struct spoolss_44 *r)
9686 {
9687         p->rng_fault_state = true;
9688         return WERR_NOT_SUPPORTED;
9689 }
9690
9691 /****************************************************************
9692  _spoolss_47
9693 ****************************************************************/
9694
9695 WERROR _spoolss_47(pipes_struct *p,
9696                    struct spoolss_47 *r)
9697 {
9698         p->rng_fault_state = true;
9699         return WERR_NOT_SUPPORTED;
9700 }
9701
9702 /****************************************************************
9703  _spoolss_4a
9704 ****************************************************************/
9705
9706 WERROR _spoolss_4a(pipes_struct *p,
9707                    struct spoolss_4a *r)
9708 {
9709         p->rng_fault_state = true;
9710         return WERR_NOT_SUPPORTED;
9711 }
9712
9713 /****************************************************************
9714  _spoolss_4b
9715 ****************************************************************/
9716
9717 WERROR _spoolss_4b(pipes_struct *p,
9718                    struct spoolss_4b *r)
9719 {
9720         p->rng_fault_state = true;
9721         return WERR_NOT_SUPPORTED;
9722 }
9723
9724 /****************************************************************
9725  _spoolss_4c
9726 ****************************************************************/
9727
9728 WERROR _spoolss_4c(pipes_struct *p,
9729                    struct spoolss_4c *r)
9730 {
9731         p->rng_fault_state = true;
9732         return WERR_NOT_SUPPORTED;
9733 }
9734
9735 /****************************************************************
9736  _spoolss_53
9737 ****************************************************************/
9738
9739 WERROR _spoolss_53(pipes_struct *p,
9740                    struct spoolss_53 *r)
9741 {
9742         p->rng_fault_state = true;
9743         return WERR_NOT_SUPPORTED;
9744 }
9745
9746 /****************************************************************
9747  _spoolss_55
9748 ****************************************************************/
9749
9750 WERROR _spoolss_55(pipes_struct *p,
9751                    struct spoolss_55 *r)
9752 {
9753         p->rng_fault_state = true;
9754         return WERR_NOT_SUPPORTED;
9755 }
9756
9757 /****************************************************************
9758  _spoolss_56
9759 ****************************************************************/
9760
9761 WERROR _spoolss_56(pipes_struct *p,
9762                    struct spoolss_56 *r)
9763 {
9764         p->rng_fault_state = true;
9765         return WERR_NOT_SUPPORTED;
9766 }
9767
9768 /****************************************************************
9769  _spoolss_57
9770 ****************************************************************/
9771
9772 WERROR _spoolss_57(pipes_struct *p,
9773                    struct spoolss_57 *r)
9774 {
9775         p->rng_fault_state = true;
9776         return WERR_NOT_SUPPORTED;
9777 }
9778
9779 /****************************************************************
9780  _spoolss_5a
9781 ****************************************************************/
9782
9783 WERROR _spoolss_5a(pipes_struct *p,
9784                    struct spoolss_5a *r)
9785 {
9786         p->rng_fault_state = true;
9787         return WERR_NOT_SUPPORTED;
9788 }
9789
9790 /****************************************************************
9791  _spoolss_5b
9792 ****************************************************************/
9793
9794 WERROR _spoolss_5b(pipes_struct *p,
9795                    struct spoolss_5b *r)
9796 {
9797         p->rng_fault_state = true;
9798         return WERR_NOT_SUPPORTED;
9799 }
9800
9801 /****************************************************************
9802  _spoolss_5c
9803 ****************************************************************/
9804
9805 WERROR _spoolss_5c(pipes_struct *p,
9806                    struct spoolss_5c *r)
9807 {
9808         p->rng_fault_state = true;
9809         return WERR_NOT_SUPPORTED;
9810 }
9811
9812 /****************************************************************
9813  _spoolss_5d
9814 ****************************************************************/
9815
9816 WERROR _spoolss_5d(pipes_struct *p,
9817                    struct spoolss_5d *r)
9818 {
9819         p->rng_fault_state = true;
9820         return WERR_NOT_SUPPORTED;
9821 }
9822
9823 /****************************************************************
9824  _spoolss_5e
9825 ****************************************************************/
9826
9827 WERROR _spoolss_5e(pipes_struct *p,
9828                    struct spoolss_5e *r)
9829 {
9830         p->rng_fault_state = true;
9831         return WERR_NOT_SUPPORTED;
9832 }
9833
9834 /****************************************************************
9835  _spoolss_5f
9836 ****************************************************************/
9837
9838 WERROR _spoolss_5f(pipes_struct *p,
9839                    struct spoolss_5f *r)
9840 {
9841         p->rng_fault_state = true;
9842         return WERR_NOT_SUPPORTED;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_60
9847 ****************************************************************/
9848
9849 WERROR _spoolss_60(pipes_struct *p,
9850                    struct spoolss_60 *r)
9851 {
9852         p->rng_fault_state = true;
9853         return WERR_NOT_SUPPORTED;
9854 }
9855
9856 /****************************************************************
9857  _spoolss_61
9858 ****************************************************************/
9859
9860 WERROR _spoolss_61(pipes_struct *p,
9861                    struct spoolss_61 *r)
9862 {
9863         p->rng_fault_state = true;
9864         return WERR_NOT_SUPPORTED;
9865 }
9866
9867 /****************************************************************
9868  _spoolss_62
9869 ****************************************************************/
9870
9871 WERROR _spoolss_62(pipes_struct *p,
9872                    struct spoolss_62 *r)
9873 {
9874         p->rng_fault_state = true;
9875         return WERR_NOT_SUPPORTED;
9876 }
9877
9878 /****************************************************************
9879  _spoolss_63
9880 ****************************************************************/
9881
9882 WERROR _spoolss_63(pipes_struct *p,
9883                    struct spoolss_63 *r)
9884 {
9885         p->rng_fault_state = true;
9886         return WERR_NOT_SUPPORTED;
9887 }
9888
9889 /****************************************************************
9890  _spoolss_64
9891 ****************************************************************/
9892
9893 WERROR _spoolss_64(pipes_struct *p,
9894                    struct spoolss_64 *r)
9895 {
9896         p->rng_fault_state = true;
9897         return WERR_NOT_SUPPORTED;
9898 }
9899
9900 /****************************************************************
9901  _spoolss_65
9902 ****************************************************************/
9903
9904 WERROR _spoolss_65(pipes_struct *p,
9905                    struct spoolss_65 *r)
9906 {
9907         p->rng_fault_state = true;
9908         return WERR_NOT_SUPPORTED;
9909 }
9910
9911 /****************************************************************
9912  _spoolss_GetCorePrinterDrivers
9913 ****************************************************************/
9914
9915 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9916                                       struct spoolss_GetCorePrinterDrivers *r)
9917 {
9918         p->rng_fault_state = true;
9919         return WERR_NOT_SUPPORTED;
9920 }
9921
9922 /****************************************************************
9923  _spoolss_67
9924 ****************************************************************/
9925
9926 WERROR _spoolss_67(pipes_struct *p,
9927                    struct spoolss_67 *r)
9928 {
9929         p->rng_fault_state = true;
9930         return WERR_NOT_SUPPORTED;
9931 }
9932
9933 /****************************************************************
9934  _spoolss_GetPrinterDriverPackagePath
9935 ****************************************************************/
9936
9937 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9938                                             struct spoolss_GetPrinterDriverPackagePath *r)
9939 {
9940         p->rng_fault_state = true;
9941         return WERR_NOT_SUPPORTED;
9942 }
9943
9944 /****************************************************************
9945  _spoolss_69
9946 ****************************************************************/
9947
9948 WERROR _spoolss_69(pipes_struct *p,
9949                    struct spoolss_69 *r)
9950 {
9951         p->rng_fault_state = true;
9952         return WERR_NOT_SUPPORTED;
9953 }
9954
9955 /****************************************************************
9956  _spoolss_6a
9957 ****************************************************************/
9958
9959 WERROR _spoolss_6a(pipes_struct *p,
9960                    struct spoolss_6a *r)
9961 {
9962         p->rng_fault_state = true;
9963         return WERR_NOT_SUPPORTED;
9964 }
9965
9966 /****************************************************************
9967  _spoolss_6b
9968 ****************************************************************/
9969
9970 WERROR _spoolss_6b(pipes_struct *p,
9971                    struct spoolss_6b *r)
9972 {
9973         p->rng_fault_state = true;
9974         return WERR_NOT_SUPPORTED;
9975 }
9976
9977 /****************************************************************
9978  _spoolss_6c
9979 ****************************************************************/
9980
9981 WERROR _spoolss_6c(pipes_struct *p,
9982                    struct spoolss_6c *r)
9983 {
9984         p->rng_fault_state = true;
9985         return WERR_NOT_SUPPORTED;
9986 }
9987
9988 /****************************************************************
9989  _spoolss_6d
9990 ****************************************************************/
9991
9992 WERROR _spoolss_6d(pipes_struct *p,
9993                    struct spoolss_6d *r)
9994 {
9995         p->rng_fault_state = true;
9996         return WERR_NOT_SUPPORTED;
9997 }