s3-spoolss: Use WERROR for print_job_delete.
[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         WERROR werr;
5125
5126         if (!Printer) {
5127                 DEBUG(2,("_spoolss_StartDocPrinter: "
5128                         "Invalid handle (%s:%u:%u)\n",
5129                         OUR_HANDLE(r->in.handle)));
5130                 return WERR_BADFID;
5131         }
5132
5133         if (Printer->jobid) {
5134                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5135                           "StartDocPrinter called twice! "
5136                           "(existing jobid = %d)\n", Printer->jobid));
5137                 return WERR_INVALID_HANDLE;
5138         }
5139
5140         if (r->in.level != 1) {
5141                 return WERR_UNKNOWN_LEVEL;
5142         }
5143
5144         info_1 = r->in.info.info1;
5145
5146         /*
5147          * a nice thing with NT is it doesn't listen to what you tell it.
5148          * when asked to send _only_ RAW datas, it tries to send datas
5149          * in EMF format.
5150          *
5151          * So I add checks like in NT Server ...
5152          */
5153
5154         if (info_1->datatype) {
5155                 if (strcmp(info_1->datatype, "RAW") != 0) {
5156                         *r->out.job_id = 0;
5157                         return WERR_INVALID_DATATYPE;
5158                 }
5159         }
5160
5161         /* get the share number of the printer */
5162         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5163                 return WERR_BADFID;
5164         }
5165
5166         werr = print_job_start(p->server_info, snum,
5167                                 info_1->document_name, info_1->output_file,
5168                                 Printer->devmode, &Printer->jobid);
5169
5170         /* An error occured in print_job_start() so return an appropriate
5171            NT error code. */
5172
5173         if (!W_ERROR_IS_OK(werr)) {
5174                 return werr;
5175         }
5176
5177         Printer->document_started = true;
5178         *r->out.job_id = Printer->jobid;
5179
5180         return WERR_OK;
5181 }
5182
5183 /****************************************************************
5184  _spoolss_EndDocPrinter
5185 ****************************************************************/
5186
5187 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5188                               struct spoolss_EndDocPrinter *r)
5189 {
5190         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5191         NTSTATUS status;
5192         int snum;
5193
5194         if (!Printer) {
5195                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5196                         OUR_HANDLE(r->in.handle)));
5197                 return WERR_BADFID;
5198         }
5199
5200         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5201                 return WERR_BADFID;
5202         }
5203
5204         Printer->document_started = false;
5205         status = print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5206         if (!NT_STATUS_IS_OK(status)) {
5207                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5208                           "print_job_end failed [%s]\n",
5209                           nt_errstr(status)));
5210         }
5211
5212         Printer->jobid = 0;
5213         return ntstatus_to_werror(status);
5214 }
5215
5216 /****************************************************************
5217  _spoolss_WritePrinter
5218 ****************************************************************/
5219
5220 WERROR _spoolss_WritePrinter(pipes_struct *p,
5221                              struct spoolss_WritePrinter *r)
5222 {
5223         ssize_t buffer_written;
5224         int snum;
5225         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5226
5227         if (!Printer) {
5228                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5229                         OUR_HANDLE(r->in.handle)));
5230                 *r->out.num_written = r->in._data_size;
5231                 return WERR_BADFID;
5232         }
5233
5234         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5235                 return WERR_BADFID;
5236
5237         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5238         buffer_written = print_job_write(snum, Printer->jobid,
5239                                                    (const char *)r->in.data.data,
5240                                                    (SMB_OFF_T)-1,
5241                                                    (size_t)r->in._data_size);
5242         if (buffer_written == (ssize_t)-1) {
5243                 *r->out.num_written = 0;
5244                 if (errno == ENOSPC)
5245                         return WERR_NO_SPOOL_SPACE;
5246                 else
5247                         return WERR_ACCESS_DENIED;
5248         }
5249
5250         *r->out.num_written = r->in._data_size;
5251
5252         return WERR_OK;
5253 }
5254
5255 /********************************************************************
5256  * api_spoolss_getprinter
5257  * called from the spoolss dispatcher
5258  *
5259  ********************************************************************/
5260
5261 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5262                               pipes_struct *p)
5263 {
5264         int snum;
5265         WERROR errcode = WERR_BADFUNC;
5266         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5267
5268         if (!Printer) {
5269                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5270                         OUR_HANDLE(handle)));
5271                 return WERR_BADFID;
5272         }
5273
5274         if (!get_printer_snum(p, handle, &snum, NULL))
5275                 return WERR_BADFID;
5276
5277         switch (command) {
5278         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5279                 errcode = print_queue_pause(p->server_info, snum);
5280                 break;
5281         case SPOOLSS_PRINTER_CONTROL_RESUME:
5282         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5283                 errcode = print_queue_resume(p->server_info, snum);
5284                 break;
5285         case SPOOLSS_PRINTER_CONTROL_PURGE:
5286                 errcode = print_queue_purge(p->server_info, snum);
5287                 break;
5288         default:
5289                 return WERR_UNKNOWN_LEVEL;
5290         }
5291
5292         return errcode;
5293 }
5294
5295
5296 /****************************************************************
5297  _spoolss_AbortPrinter
5298  * From MSDN: "Deletes printer's spool file if printer is configured
5299  * for spooling"
5300 ****************************************************************/
5301
5302 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5303                              struct spoolss_AbortPrinter *r)
5304 {
5305         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5306         int             snum;
5307         WERROR          errcode = WERR_OK;
5308
5309         if (!Printer) {
5310                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5311                         OUR_HANDLE(r->in.handle)));
5312                 return WERR_BADFID;
5313         }
5314
5315         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5316                 return WERR_BADFID;
5317
5318         if (!Printer->document_started) {
5319                 return WERR_SPL_NO_STARTDOC;
5320         }
5321
5322         errcode = print_job_delete(p->server_info, snum, Printer->jobid);
5323
5324         return errcode;
5325 }
5326
5327 /********************************************************************
5328  * called by spoolss_api_setprinter
5329  * when updating a printer description
5330  ********************************************************************/
5331
5332 static WERROR update_printer_sec(struct policy_handle *handle,
5333                                  pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5334 {
5335         struct spoolss_security_descriptor *new_secdesc = NULL;
5336         struct spoolss_security_descriptor *old_secdesc = NULL;
5337         const char *printer;
5338         WERROR result;
5339         int snum;
5340
5341         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5342
5343         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5344                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5345                          OUR_HANDLE(handle)));
5346
5347                 result = WERR_BADFID;
5348                 goto done;
5349         }
5350
5351         if (secdesc_ctr == NULL) {
5352                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5353                 result = WERR_INVALID_PARAM;
5354                 goto done;
5355         }
5356         printer = lp_const_servicename(snum);
5357
5358         /* Check the user has permissions to change the security
5359            descriptor.  By experimentation with two NT machines, the user
5360            requires Full Access to the printer to change security
5361            information. */
5362
5363         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5364                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5365                 result = WERR_ACCESS_DENIED;
5366                 goto done;
5367         }
5368
5369         /* NT seems to like setting the security descriptor even though
5370            nothing may have actually changed. */
5371         result = winreg_get_printer_secdesc(p->mem_ctx,
5372                                             p->server_info,
5373                                             printer,
5374                                             &old_secdesc);
5375         if (!W_ERROR_IS_OK(result)) {
5376                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5377                 result = WERR_BADFID;
5378                 goto done;
5379         }
5380
5381         if (DEBUGLEVEL >= 10) {
5382                 struct security_acl *the_acl;
5383                 int i;
5384
5385                 the_acl = secdesc_ctr->sd->dacl;
5386                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5387                            printer, the_acl->num_aces));
5388
5389                 for (i = 0; i < the_acl->num_aces; i++) {
5390                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5391                                            &the_acl->aces[i].trustee),
5392                                   the_acl->aces[i].access_mask));
5393                 }
5394
5395                 the_acl = secdesc_ctr->sd->dacl;
5396
5397                 if (the_acl) {
5398                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5399                                    printer, the_acl->num_aces));
5400
5401                         for (i = 0; i < the_acl->num_aces; i++) {
5402                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5403                                                    &the_acl->aces[i].trustee),
5404                                            the_acl->aces[i].access_mask));
5405                         }
5406                 } else {
5407                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5408                 }
5409         }
5410
5411         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5412         if (new_secdesc == NULL) {
5413                 result = WERR_NOMEM;
5414                 goto done;
5415         }
5416
5417         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5418                 result = WERR_OK;
5419                 goto done;
5420         }
5421
5422         result = winreg_set_printer_secdesc(p->mem_ctx,
5423                                             p->server_info,
5424                                             printer,
5425                                             new_secdesc);
5426
5427  done:
5428         return result;
5429 }
5430
5431 /********************************************************************
5432  Canonicalize printer info from a client
5433  ********************************************************************/
5434
5435 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5436                              struct spoolss_SetPrinterInfo2 *info2,
5437                              int snum)
5438 {
5439         fstring printername;
5440         const char *p;
5441
5442         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5443                 "portname=%s drivername=%s comment=%s location=%s\n",
5444                 info2->servername, info2->printername, info2->sharename,
5445                 info2->portname, info2->drivername, info2->comment,
5446                 info2->location));
5447
5448         /* we force some elements to "correct" values */
5449         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5450         if (info2->servername == NULL) {
5451                 return false;
5452         }
5453         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5454         if (info2->sharename == NULL) {
5455                 return false;
5456         }
5457
5458         /* check to see if we allow printername != sharename */
5459         if (lp_force_printername(snum)) {
5460                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5461                                         global_myname(), info2->sharename);
5462         } else {
5463                 /* make sure printername is in \\server\printername format */
5464                 fstrcpy(printername, info2->printername);
5465                 p = printername;
5466                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5467                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5468                                 p++;
5469                 }
5470
5471                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5472                                         global_myname(), p);
5473         }
5474         if (info2->printername == NULL) {
5475                 return false;
5476         }
5477
5478         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5479         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5480
5481         return true;
5482 }
5483
5484 /****************************************************************************
5485 ****************************************************************************/
5486
5487 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5488 {
5489         char *cmd = lp_addport_cmd();
5490         char *command = NULL;
5491         int ret;
5492         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5493         bool is_print_op = false;
5494
5495         if ( !*cmd ) {
5496                 return WERR_ACCESS_DENIED;
5497         }
5498
5499         command = talloc_asprintf(ctx,
5500                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5501         if (!command) {
5502                 return WERR_NOMEM;
5503         }
5504
5505         if ( token )
5506                 is_print_op = user_has_privileges( token, &se_printop );
5507
5508         DEBUG(10,("Running [%s]\n", command));
5509
5510         /********* BEGIN SePrintOperatorPrivilege **********/
5511
5512         if ( is_print_op )
5513                 become_root();
5514
5515         ret = smbrun(command, NULL);
5516
5517         if ( is_print_op )
5518                 unbecome_root();
5519
5520         /********* END SePrintOperatorPrivilege **********/
5521
5522         DEBUGADD(10,("returned [%d]\n", ret));
5523
5524         TALLOC_FREE(command);
5525
5526         if ( ret != 0 ) {
5527                 return WERR_ACCESS_DENIED;
5528         }
5529
5530         return WERR_OK;
5531 }
5532
5533 /****************************************************************************
5534 ****************************************************************************/
5535
5536 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5537                       struct spoolss_SetPrinterInfo2 *info2)
5538 {
5539         char *cmd = lp_addprinter_cmd();
5540         char **qlines;
5541         char *command = NULL;
5542         int numlines;
5543         int ret;
5544         int fd;
5545         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5546         bool is_print_op = false;
5547         char *remote_machine = talloc_strdup(ctx, "%m");
5548
5549         if (!remote_machine) {
5550                 return false;
5551         }
5552         remote_machine = talloc_sub_basic(ctx,
5553                                 current_user_info.smb_name,
5554                                 current_user_info.domain,
5555                                 remote_machine);
5556         if (!remote_machine) {
5557                 return false;
5558         }
5559
5560         command = talloc_asprintf(ctx,
5561                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5562                         cmd, info2->printername, info2->sharename,
5563                         info2->portname, info2->drivername,
5564                         info2->location, info2->comment, remote_machine);
5565         if (!command) {
5566                 return false;
5567         }
5568
5569         if ( token )
5570                 is_print_op = user_has_privileges( token, &se_printop );
5571
5572         DEBUG(10,("Running [%s]\n", command));
5573
5574         /********* BEGIN SePrintOperatorPrivilege **********/
5575
5576         if ( is_print_op )
5577                 become_root();
5578
5579         if ( (ret = smbrun(command, &fd)) == 0 ) {
5580                 /* Tell everyone we updated smb.conf. */
5581                 message_send_all(smbd_messaging_context(),
5582                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5583         }
5584
5585         if ( is_print_op )
5586                 unbecome_root();
5587
5588         /********* END SePrintOperatorPrivilege **********/
5589
5590         DEBUGADD(10,("returned [%d]\n", ret));
5591
5592         TALLOC_FREE(command);
5593         TALLOC_FREE(remote_machine);
5594
5595         if ( ret != 0 ) {
5596                 if (fd != -1)
5597                         close(fd);
5598                 return false;
5599         }
5600
5601         /* reload our services immediately */
5602         become_root();
5603         reload_services(false);
5604         unbecome_root();
5605
5606         numlines = 0;
5607         /* Get lines and convert them back to dos-codepage */
5608         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5609         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5610         close(fd);
5611
5612         /* Set the portname to what the script says the portname should be. */
5613         /* but don't require anything to be return from the script exit a good error code */
5614
5615         if (numlines) {
5616                 /* Set the portname to what the script says the portname should be. */
5617                 info2->portname = talloc_strdup(ctx, qlines[0]);
5618                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5619         }
5620
5621         TALLOC_FREE(qlines);
5622         return true;
5623 }
5624
5625 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5626                                struct auth_serversupplied_info *server_info,
5627                                int snum,
5628                                struct spoolss_SetPrinterInfo2 *printer,
5629                                struct spoolss_PrinterInfo2 *old_printer)
5630 {
5631         bool force_update = (old_printer == NULL);
5632         const char *dnsdomname;
5633         const char *longname;
5634         const char *uncname;
5635         const char *spooling;
5636         DATA_BLOB buffer;
5637         WERROR result = WERR_OK;
5638
5639         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5640                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5641                 winreg_set_printer_dataex(mem_ctx,
5642                                           server_info,
5643                                           printer->sharename,
5644                                           SPOOL_DSSPOOLER_KEY,
5645                                           SPOOL_REG_DRIVERNAME,
5646                                           REG_SZ,
5647                                           buffer.data,
5648                                           buffer.length);
5649
5650                 if (!force_update) {
5651                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5652                                 printer->drivername));
5653
5654                         notify_printer_driver(snum, printer->drivername);
5655                 }
5656         }
5657
5658         if (force_update || !strequal(printer->comment, old_printer->comment)) {
5659                 push_reg_sz(mem_ctx, &buffer, printer->comment);
5660                 winreg_set_printer_dataex(mem_ctx,
5661                                           server_info,
5662                                           printer->sharename,
5663                                           SPOOL_DSSPOOLER_KEY,
5664                                           SPOOL_REG_DESCRIPTION,
5665                                           REG_SZ,
5666                                           buffer.data,
5667                                           buffer.length);
5668
5669                 if (!force_update) {
5670                         notify_printer_comment(snum, printer->comment);
5671                 }
5672         }
5673
5674         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5675                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5676                 winreg_set_printer_dataex(mem_ctx,
5677                                           server_info,
5678                                           printer->sharename,
5679                                           SPOOL_DSSPOOLER_KEY,
5680                                           SPOOL_REG_PRINTSHARENAME,
5681                                           REG_SZ,
5682                                           buffer.data,
5683                                           buffer.length);
5684
5685                 if (!force_update) {
5686                         notify_printer_sharename(snum, printer->sharename);
5687                 }
5688         }
5689
5690         if (force_update || !strequal(printer->printername, old_printer->printername)) {
5691                 const char *p;
5692
5693                 p = strrchr(printer->printername, '\\' );
5694                 if (p != NULL) {
5695                         p++;
5696                 } else {
5697                         p = printer->printername;
5698                 }
5699
5700                 push_reg_sz(mem_ctx, &buffer, p);
5701                 winreg_set_printer_dataex(mem_ctx,
5702                                           server_info,
5703                                           printer->sharename,
5704                                           SPOOL_DSSPOOLER_KEY,
5705                                           SPOOL_REG_PRINTERNAME,
5706                                           REG_SZ,
5707                                           buffer.data,
5708                                           buffer.length);
5709
5710                 if (!force_update) {
5711                         notify_printer_printername(snum, p);
5712                 }
5713         }
5714
5715         if (force_update || !strequal(printer->portname, old_printer->portname)) {
5716                 push_reg_sz(mem_ctx, &buffer, printer->portname);
5717                 winreg_set_printer_dataex(mem_ctx,
5718                                           server_info,
5719                                           printer->sharename,
5720                                           SPOOL_DSSPOOLER_KEY,
5721                                           SPOOL_REG_PORTNAME,
5722                                           REG_SZ,
5723                                           buffer.data,
5724                                           buffer.length);
5725
5726                 if (!force_update) {
5727                         notify_printer_port(snum, printer->portname);
5728                 }
5729         }
5730
5731         if (force_update || !strequal(printer->location, old_printer->location)) {
5732                 push_reg_sz(mem_ctx, &buffer, printer->location);
5733                 winreg_set_printer_dataex(mem_ctx,
5734                                           server_info,
5735                                           printer->sharename,
5736                                           SPOOL_DSSPOOLER_KEY,
5737                                           SPOOL_REG_LOCATION,
5738                                           REG_SZ,
5739                                           buffer.data,
5740                                           buffer.length);
5741
5742                 if (!force_update) {
5743                         notify_printer_location(snum, printer->location);
5744                 }
5745         }
5746
5747         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
5748                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
5749                 winreg_set_printer_dataex(mem_ctx,
5750                                           server_info,
5751                                           printer->sharename,
5752                                           SPOOL_DSSPOOLER_KEY,
5753                                           SPOOL_REG_PRINTSEPARATORFILE,
5754                                           REG_SZ,
5755                                           buffer.data,
5756                                           buffer.length);
5757
5758                 if (!force_update) {
5759                         notify_printer_location(snum, printer->location);
5760                 }
5761         }
5762
5763         if (force_update || printer->starttime != old_printer->starttime) {
5764                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5765                 SIVAL(buffer.data, 0, printer->starttime);
5766                 winreg_set_printer_dataex(mem_ctx,
5767                                           server_info,
5768                                           printer->sharename,
5769                                           SPOOL_DSSPOOLER_KEY,
5770                                           SPOOL_REG_PRINTSTARTTIME,
5771                                           REG_DWORD,
5772                                           buffer.data,
5773                                           buffer.length);
5774         }
5775
5776         if (force_update || printer->untiltime != old_printer->untiltime) {
5777                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5778                 SIVAL(buffer.data, 0, printer->untiltime);
5779                 winreg_set_printer_dataex(mem_ctx,
5780                                           server_info,
5781                                           printer->sharename,
5782                                           SPOOL_DSSPOOLER_KEY,
5783                                           SPOOL_REG_PRINTENDTIME,
5784                                           REG_DWORD,
5785                                           buffer.data,
5786                                           buffer.length);
5787         }
5788
5789         if (force_update || printer->priority != old_printer->priority) {
5790                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5791                 SIVAL(buffer.data, 0, printer->priority);
5792                 winreg_set_printer_dataex(mem_ctx,
5793                                           server_info,
5794                                           printer->sharename,
5795                                           SPOOL_DSSPOOLER_KEY,
5796                                           SPOOL_REG_PRIORITY,
5797                                           REG_DWORD,
5798                                           buffer.data,
5799                                           buffer.length);
5800         }
5801
5802         if (force_update || printer->attributes != old_printer->attributes) {
5803                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5804                 SIVAL(buffer.data, 0, (printer->attributes &
5805                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
5806                 winreg_set_printer_dataex(mem_ctx,
5807                                           server_info,
5808                                           printer->sharename,
5809                                           SPOOL_DSSPOOLER_KEY,
5810                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
5811                                           REG_DWORD,
5812                                           buffer.data,
5813                                           buffer.length);
5814
5815                 switch (printer->attributes & 0x3) {
5816                         case 0:
5817                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
5818                                 break;
5819                         case 1:
5820                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
5821                                 break;
5822                         case 2:
5823                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
5824                                 break;
5825                         default:
5826                                 spooling = "unknown";
5827                 }
5828                 push_reg_sz(mem_ctx, &buffer, spooling);
5829                 winreg_set_printer_dataex(mem_ctx,
5830                                           server_info,
5831                                           printer->sharename,
5832                                           SPOOL_DSSPOOLER_KEY,
5833                                           SPOOL_REG_PRINTSPOOLING,
5834                                           REG_SZ,
5835                                           buffer.data,
5836                                           buffer.length);
5837         }
5838
5839         push_reg_sz(mem_ctx, &buffer, global_myname());
5840         winreg_set_printer_dataex(mem_ctx,
5841                                   server_info,
5842                                   printer->sharename,
5843                                   SPOOL_DSSPOOLER_KEY,
5844                                   SPOOL_REG_SHORTSERVERNAME,
5845                                   REG_SZ,
5846                                   buffer.data,
5847                                   buffer.length);
5848
5849         dnsdomname = get_mydnsfullname();
5850         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
5851                 longname = talloc_strdup(mem_ctx, dnsdomname);
5852         } else {
5853                 longname = talloc_strdup(mem_ctx, global_myname());
5854         }
5855         if (longname == NULL) {
5856                 result = WERR_NOMEM;
5857                 goto done;
5858         }
5859
5860         push_reg_sz(mem_ctx, &buffer, longname);
5861         winreg_set_printer_dataex(mem_ctx,
5862                                   server_info,
5863                                   printer->sharename,
5864                                   SPOOL_DSSPOOLER_KEY,
5865                                   SPOOL_REG_SERVERNAME,
5866                                   REG_SZ,
5867                                   buffer.data,
5868                                   buffer.length);
5869
5870         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5871                                   global_myname(), printer->sharename);
5872         push_reg_sz(mem_ctx, &buffer, uncname);
5873         winreg_set_printer_dataex(mem_ctx,
5874                                   server_info,
5875                                   printer->sharename,
5876                                   SPOOL_DSSPOOLER_KEY,
5877                                   SPOOL_REG_UNCNAME,
5878                                   REG_SZ,
5879                                   buffer.data,
5880                                   buffer.length);
5881
5882 done:
5883         return result;
5884 }
5885
5886 /********************************************************************
5887  * Called by spoolss_api_setprinter
5888  * when updating a printer description.
5889  ********************************************************************/
5890
5891 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5892                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5893                              struct spoolss_DeviceMode *devmode)
5894 {
5895         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5896         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5897         struct spoolss_PrinterInfo2 *old_printer;
5898         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5899         const char *servername = NULL;
5900         int snum;
5901         WERROR result = WERR_OK;
5902         TALLOC_CTX *tmp_ctx;
5903
5904         DEBUG(8,("update_printer\n"));
5905
5906         tmp_ctx = talloc_new(p->mem_ctx);
5907         if (tmp_ctx == NULL) {
5908                 return WERR_NOMEM;
5909         }
5910
5911         if (!Printer) {
5912                 result = WERR_BADFID;
5913                 goto done;
5914         }
5915
5916         if (!get_printer_snum(p, handle, &snum, NULL)) {
5917                 result = WERR_BADFID;
5918                 goto done;
5919         }
5920
5921         if (Printer != NULL || Printer->servername != NULL) {
5922                 servername = Printer->servername;
5923         }
5924
5925         result = winreg_get_printer(tmp_ctx,
5926                                     p->server_info,
5927                                     servername,
5928                                     lp_const_servicename(snum),
5929                                     &old_printer);
5930         if (!W_ERROR_IS_OK(result)) {
5931                 result = WERR_BADFID;
5932                 goto done;
5933         }
5934
5935         /* Do sanity check on the requested changes for Samba */
5936         if (!check_printer_ok(tmp_ctx, printer, snum)) {
5937                 result = WERR_INVALID_PARAM;
5938                 goto done;
5939         }
5940
5941         /* FIXME!!! If the driver has changed we really should verify that
5942            it is installed before doing much else   --jerry */
5943
5944         /* Check calling user has permission to update printer description */
5945         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5946                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5947                 result = WERR_ACCESS_DENIED;
5948                 goto done;
5949         }
5950
5951         /* Call addprinter hook */
5952         /* Check changes to see if this is really needed */
5953
5954         if (*lp_addprinter_cmd() &&
5955                         (!strequal(printer->drivername, old_printer->drivername) ||
5956                          !strequal(printer->comment, old_printer->comment) ||
5957                          !strequal(printer->portname, old_printer->portname) ||
5958                          !strequal(printer->location, old_printer->location)) )
5959         {
5960                 /* add_printer_hook() will call reload_services() */
5961                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
5962                                       printer) ) {
5963                         result = WERR_ACCESS_DENIED;
5964                         goto done;
5965                 }
5966         }
5967
5968         update_dsspooler(tmp_ctx,
5969                          p->server_info,
5970                          snum,
5971                          printer,
5972                          old_printer);
5973
5974         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5975
5976         if (devmode == NULL) {
5977                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5978         }
5979         result = winreg_update_printer(tmp_ctx,
5980                                        p->server_info,
5981                                        printer->sharename,
5982                                        printer_mask,
5983                                        printer,
5984                                        devmode,
5985                                        NULL);
5986
5987 done:
5988         talloc_free(tmp_ctx);
5989
5990         return result;
5991 }
5992
5993 /****************************************************************************
5994 ****************************************************************************/
5995 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5996                                            struct policy_handle *handle,
5997                                            struct spoolss_SetPrinterInfo7 *info7)
5998 {
5999 #ifdef HAVE_ADS
6000         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6001         WERROR result;
6002         int snum;
6003         Printer_entry *Printer;
6004
6005         if ( lp_security() != SEC_ADS ) {
6006                 return WERR_UNKNOWN_LEVEL;
6007         }
6008
6009         Printer = find_printer_index_by_hnd(p, handle);
6010
6011         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6012
6013         if (!Printer)
6014                 return WERR_BADFID;
6015
6016         if (!get_printer_snum(p, handle, &snum, NULL))
6017                 return WERR_BADFID;
6018
6019         result = winreg_get_printer(p->mem_ctx, p->server_info,
6020                                     Printer->servername,
6021                                     lp_servicename(snum), &pinfo2);
6022         if (!W_ERROR_IS_OK(result)) {
6023                 return WERR_BADFID;
6024         }
6025
6026         nt_printer_publish(pinfo2, p->server_info, pinfo2, info7->action);
6027
6028         TALLOC_FREE(pinfo2);
6029         return WERR_OK;
6030 #else
6031         return WERR_UNKNOWN_LEVEL;
6032 #endif
6033 }
6034
6035 /********************************************************************
6036  ********************************************************************/
6037
6038 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
6039                                      struct spoolss_DeviceMode *devmode)
6040 {
6041         int snum;
6042         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6043         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6044
6045         DEBUG(8,("update_printer_devmode\n"));
6046
6047         if (!Printer) {
6048                 return WERR_BADFID;
6049         }
6050
6051         if (!get_printer_snum(p, handle, &snum, NULL)) {
6052                 return WERR_BADFID;
6053         }
6054
6055         /* Check calling user has permission to update printer description */
6056         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6057                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6058                 return WERR_ACCESS_DENIED;
6059         }
6060
6061         return winreg_update_printer(p->mem_ctx,
6062                                      p->server_info,
6063                                      lp_const_servicename(snum),
6064                                      info2_mask,
6065                                      NULL,
6066                                      devmode,
6067                                      NULL);
6068 }
6069
6070
6071 /****************************************************************
6072  _spoolss_SetPrinter
6073 ****************************************************************/
6074
6075 WERROR _spoolss_SetPrinter(pipes_struct *p,
6076                            struct spoolss_SetPrinter *r)
6077 {
6078         WERROR result;
6079
6080         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6081
6082         if (!Printer) {
6083                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6084                         OUR_HANDLE(r->in.handle)));
6085                 return WERR_BADFID;
6086         }
6087
6088         /* check the level */
6089         switch (r->in.info_ctr->level) {
6090                 case 0:
6091                         return control_printer(r->in.handle, r->in.command, p);
6092                 case 2:
6093                         result = update_printer(p, r->in.handle,
6094                                                 r->in.info_ctr,
6095                                                 r->in.devmode_ctr->devmode);
6096                         if (!W_ERROR_IS_OK(result))
6097                                 return result;
6098                         if (r->in.secdesc_ctr->sd)
6099                                 result = update_printer_sec(r->in.handle, p,
6100                                                             r->in.secdesc_ctr);
6101                         return result;
6102                 case 3:
6103                         return update_printer_sec(r->in.handle, p,
6104                                                   r->in.secdesc_ctr);
6105                 case 7:
6106                         return publish_or_unpublish_printer(p, r->in.handle,
6107                                                             r->in.info_ctr->info.info7);
6108                 case 8:
6109                         return update_printer_devmode(p, r->in.handle,
6110                                                       r->in.devmode_ctr->devmode);
6111                 default:
6112                         return WERR_UNKNOWN_LEVEL;
6113         }
6114 }
6115
6116 /****************************************************************
6117  _spoolss_FindClosePrinterNotify
6118 ****************************************************************/
6119
6120 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6121                                        struct spoolss_FindClosePrinterNotify *r)
6122 {
6123         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6124
6125         if (!Printer) {
6126                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6127                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6128                 return WERR_BADFID;
6129         }
6130
6131         if (Printer->notify.client_connected == true) {
6132                 int snum = -1;
6133
6134                 if ( Printer->printer_type == SPLHND_SERVER)
6135                         snum = -1;
6136                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6137                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6138                         return WERR_BADFID;
6139
6140                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6141         }
6142
6143         Printer->notify.flags=0;
6144         Printer->notify.options=0;
6145         Printer->notify.localmachine[0]='\0';
6146         Printer->notify.printerlocal=0;
6147         TALLOC_FREE(Printer->notify.option);
6148         Printer->notify.client_connected = false;
6149
6150         return WERR_OK;
6151 }
6152
6153 /****************************************************************
6154  _spoolss_AddJob
6155 ****************************************************************/
6156
6157 WERROR _spoolss_AddJob(pipes_struct *p,
6158                        struct spoolss_AddJob *r)
6159 {
6160         if (!r->in.buffer && (r->in.offered != 0)) {
6161                 return WERR_INVALID_PARAM;
6162         }
6163
6164         /* this is what a NT server returns for AddJob. AddJob must fail on
6165          * non-local printers */
6166
6167         if (r->in.level != 1) {
6168                 return WERR_UNKNOWN_LEVEL;
6169         }
6170
6171         return WERR_INVALID_PARAM;
6172 }
6173
6174 /****************************************************************************
6175 fill_job_info1
6176 ****************************************************************************/
6177
6178 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6179                              struct spoolss_JobInfo1 *r,
6180                              const print_queue_struct *queue,
6181                              int position, int snum,
6182                              struct spoolss_PrinterInfo2 *pinfo2)
6183 {
6184         struct tm *t;
6185
6186         t = gmtime(&queue->time);
6187
6188         r->job_id               = queue->job;
6189
6190         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6191         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6192         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6193         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6194         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6195         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6196         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6197         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6198         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6199         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6200         r->text_status          = talloc_strdup(mem_ctx, "");
6201         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6202
6203         r->status               = nt_printj_status(queue->status);
6204         r->priority             = queue->priority;
6205         r->position             = position;
6206         r->total_pages          = queue->page_count;
6207         r->pages_printed        = 0; /* ??? */
6208
6209         init_systemtime(&r->submitted, t);
6210
6211         return WERR_OK;
6212 }
6213
6214 /****************************************************************************
6215 fill_job_info2
6216 ****************************************************************************/
6217
6218 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6219                              struct spoolss_JobInfo2 *r,
6220                              const print_queue_struct *queue,
6221                              int position, int snum,
6222                              struct spoolss_PrinterInfo2 *pinfo2,
6223                              struct spoolss_DeviceMode *devmode)
6224 {
6225         struct tm *t;
6226
6227         t = gmtime(&queue->time);
6228
6229         r->job_id               = queue->job;
6230
6231         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6232         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6233         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6234         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6235         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6236         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6237         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6238         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6239         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6240         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6241         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6242         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6243         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6244         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6245         r->parameters           = talloc_strdup(mem_ctx, "");
6246         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6247         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6248         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6249
6250         r->devmode              = devmode;
6251
6252         r->text_status          = talloc_strdup(mem_ctx, "");
6253         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6254
6255         r->secdesc              = NULL;
6256
6257         r->status               = nt_printj_status(queue->status);
6258         r->priority             = queue->priority;
6259         r->position             = position;
6260         r->start_time           = 0;
6261         r->until_time           = 0;
6262         r->total_pages          = queue->page_count;
6263         r->size                 = queue->size;
6264         init_systemtime(&r->submitted, t);
6265         r->time                 = 0;
6266         r->pages_printed        = 0; /* ??? */
6267
6268         return WERR_OK;
6269 }
6270
6271 /****************************************************************************
6272 fill_job_info3
6273 ****************************************************************************/
6274
6275 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6276                              struct spoolss_JobInfo3 *r,
6277                              const print_queue_struct *queue,
6278                              const print_queue_struct *next_queue,
6279                              int position, int snum,
6280                              struct spoolss_PrinterInfo2 *pinfo2)
6281 {
6282         r->job_id               = queue->job;
6283         r->next_job_id          = 0;
6284         if (next_queue) {
6285                 r->next_job_id  = next_queue->job;
6286         }
6287         r->reserved             = 0;
6288
6289         return WERR_OK;
6290 }
6291
6292 /****************************************************************************
6293  Enumjobs at level 1.
6294 ****************************************************************************/
6295
6296 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6297                               const print_queue_struct *queue,
6298                               uint32_t num_queues, int snum,
6299                               struct spoolss_PrinterInfo2 *pinfo2,
6300                               union spoolss_JobInfo **info_p,
6301                               uint32_t *count)
6302 {
6303         union spoolss_JobInfo *info;
6304         int i;
6305         WERROR result = WERR_OK;
6306
6307         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6308         W_ERROR_HAVE_NO_MEMORY(info);
6309
6310         *count = num_queues;
6311
6312         for (i=0; i<*count; i++) {
6313                 result = fill_job_info1(info,
6314                                         &info[i].info1,
6315                                         &queue[i],
6316                                         i,
6317                                         snum,
6318                                         pinfo2);
6319                 if (!W_ERROR_IS_OK(result)) {
6320                         goto out;
6321                 }
6322         }
6323
6324  out:
6325         if (!W_ERROR_IS_OK(result)) {
6326                 TALLOC_FREE(info);
6327                 *count = 0;
6328                 return result;
6329         }
6330
6331         *info_p = info;
6332
6333         return WERR_OK;
6334 }
6335
6336 /****************************************************************************
6337  Enumjobs at level 2.
6338 ****************************************************************************/
6339
6340 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6341                               const print_queue_struct *queue,
6342                               uint32_t num_queues, int snum,
6343                               struct spoolss_PrinterInfo2 *pinfo2,
6344                               union spoolss_JobInfo **info_p,
6345                               uint32_t *count)
6346 {
6347         union spoolss_JobInfo *info;
6348         int i;
6349         WERROR result = WERR_OK;
6350
6351         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6352         W_ERROR_HAVE_NO_MEMORY(info);
6353
6354         *count = num_queues;
6355
6356         for (i=0; i<*count; i++) {
6357                 struct spoolss_DeviceMode *devmode;
6358
6359                 result = spoolss_create_default_devmode(info,
6360                                                         pinfo2->printername,
6361                                                         &devmode);
6362                 if (!W_ERROR_IS_OK(result)) {
6363                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6364                         goto out;
6365                 }
6366
6367                 result = fill_job_info2(info,
6368                                         &info[i].info2,
6369                                         &queue[i],
6370                                         i,
6371                                         snum,
6372                                         pinfo2,
6373                                         devmode);
6374                 if (!W_ERROR_IS_OK(result)) {
6375                         goto out;
6376                 }
6377         }
6378
6379  out:
6380         if (!W_ERROR_IS_OK(result)) {
6381                 TALLOC_FREE(info);
6382                 *count = 0;
6383                 return result;
6384         }
6385
6386         *info_p = info;
6387
6388         return WERR_OK;
6389 }
6390
6391 /****************************************************************************
6392  Enumjobs at level 3.
6393 ****************************************************************************/
6394
6395 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6396                               const print_queue_struct *queue,
6397                               uint32_t num_queues, int snum,
6398                               struct spoolss_PrinterInfo2 *pinfo2,
6399                               union spoolss_JobInfo **info_p,
6400                               uint32_t *count)
6401 {
6402         union spoolss_JobInfo *info;
6403         int i;
6404         WERROR result = WERR_OK;
6405
6406         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6407         W_ERROR_HAVE_NO_MEMORY(info);
6408
6409         *count = num_queues;
6410
6411         for (i=0; i<*count; i++) {
6412                 const print_queue_struct *next_queue = NULL;
6413
6414                 if (i+1 < *count) {
6415                         next_queue = &queue[i+1];
6416                 }
6417
6418                 result = fill_job_info3(info,
6419                                         &info[i].info3,
6420                                         &queue[i],
6421                                         next_queue,
6422                                         i,
6423                                         snum,
6424                                         pinfo2);
6425                 if (!W_ERROR_IS_OK(result)) {
6426                         goto out;
6427                 }
6428         }
6429
6430  out:
6431         if (!W_ERROR_IS_OK(result)) {
6432                 TALLOC_FREE(info);
6433                 *count = 0;
6434                 return result;
6435         }
6436
6437         *info_p = info;
6438
6439         return WERR_OK;
6440 }
6441
6442 /****************************************************************
6443  _spoolss_EnumJobs
6444 ****************************************************************/
6445
6446 WERROR _spoolss_EnumJobs(pipes_struct *p,
6447                          struct spoolss_EnumJobs *r)
6448 {
6449         WERROR result;
6450         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6451         int snum;
6452         print_status_struct prt_status;
6453         print_queue_struct *queue = NULL;
6454         uint32_t count;
6455
6456         /* that's an [in out] buffer */
6457
6458         if (!r->in.buffer && (r->in.offered != 0)) {
6459                 return WERR_INVALID_PARAM;
6460         }
6461
6462         DEBUG(4,("_spoolss_EnumJobs\n"));
6463
6464         *r->out.needed = 0;
6465         *r->out.count = 0;
6466         *r->out.info = NULL;
6467
6468         /* lookup the printer snum and tdb entry */
6469
6470         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6471                 return WERR_BADFID;
6472         }
6473
6474         result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
6475                                     lp_servicename(snum), &pinfo2);
6476         if (!W_ERROR_IS_OK(result)) {
6477                 return result;
6478         }
6479
6480         count = print_queue_status(snum, &queue, &prt_status);
6481         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6482                 count, prt_status.status, prt_status.message));
6483
6484         if (count == 0) {
6485                 SAFE_FREE(queue);
6486                 TALLOC_FREE(pinfo2);
6487                 return WERR_OK;
6488         }
6489
6490         switch (r->in.level) {
6491         case 1:
6492                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6493                                          pinfo2, r->out.info, r->out.count);
6494                 break;
6495         case 2:
6496                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6497                                          pinfo2, r->out.info, r->out.count);
6498                 break;
6499         case 3:
6500                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6501                                          pinfo2, r->out.info, r->out.count);
6502                 break;
6503         default:
6504                 result = WERR_UNKNOWN_LEVEL;
6505                 break;
6506         }
6507
6508         SAFE_FREE(queue);
6509         TALLOC_FREE(pinfo2);
6510
6511         if (!W_ERROR_IS_OK(result)) {
6512                 return result;
6513         }
6514
6515         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6516                                                      spoolss_EnumJobs, 
6517                                                      *r->out.info, r->in.level,
6518                                                      *r->out.count);
6519         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6520         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6521
6522         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6523 }
6524
6525 /****************************************************************
6526  _spoolss_ScheduleJob
6527 ****************************************************************/
6528
6529 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6530                             struct spoolss_ScheduleJob *r)
6531 {
6532         return WERR_OK;
6533 }
6534
6535 /****************************************************************
6536 ****************************************************************/
6537
6538 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6539                                const char *printer_name,
6540                                uint32_t job_id,
6541                                struct spoolss_SetJobInfo1 *r)
6542 {
6543         char *old_doc_name;
6544
6545         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6546                 return WERR_BADFID;
6547         }
6548
6549         if (strequal(old_doc_name, r->document_name)) {
6550                 return WERR_OK;
6551         }
6552
6553         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6554                 return WERR_BADFID;
6555         }
6556
6557         return WERR_OK;
6558 }
6559
6560 /****************************************************************
6561  _spoolss_SetJob
6562 ****************************************************************/
6563
6564 WERROR _spoolss_SetJob(pipes_struct *p,
6565                        struct spoolss_SetJob *r)
6566 {
6567         int snum;
6568         WERROR errcode = WERR_BADFUNC;
6569
6570         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6571                 return WERR_BADFID;
6572         }
6573
6574         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6575                 return WERR_INVALID_PRINTER_NAME;
6576         }
6577
6578         switch (r->in.command) {
6579         case SPOOLSS_JOB_CONTROL_CANCEL:
6580         case SPOOLSS_JOB_CONTROL_DELETE:
6581                 errcode = print_job_delete(p->server_info,
6582                                            snum, r->in.job_id);
6583                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6584                         errcode = WERR_OK;
6585                 }
6586                 break;
6587         case SPOOLSS_JOB_CONTROL_PAUSE:
6588                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6589                         errcode = WERR_OK;
6590                 }
6591                 break;
6592         case SPOOLSS_JOB_CONTROL_RESTART:
6593         case SPOOLSS_JOB_CONTROL_RESUME:
6594                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6595                         errcode = WERR_OK;
6596                 }
6597                 break;
6598         case 0:
6599                 errcode = WERR_OK;
6600                 break;
6601         default:
6602                 return WERR_UNKNOWN_LEVEL;
6603         }
6604
6605         if (!W_ERROR_IS_OK(errcode)) {
6606                 return errcode;
6607         }
6608
6609         if (r->in.ctr == NULL) {
6610                 return errcode;
6611         }
6612
6613         switch (r->in.ctr->level) {
6614         case 1:
6615                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6616                                            r->in.job_id,
6617                                            r->in.ctr->info.info1);
6618                 break;
6619         case 2:
6620         case 3:
6621         case 4:
6622         default:
6623                 return WERR_UNKNOWN_LEVEL;
6624         }
6625
6626         return errcode;
6627 }
6628
6629 /****************************************************************************
6630  Enumerates all printer drivers by level and architecture.
6631 ****************************************************************************/
6632
6633 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6634                                                        struct auth_serversupplied_info *server_info,
6635                                                        const char *servername,
6636                                                        const char *architecture,
6637                                                        uint32_t level,
6638                                                        union spoolss_DriverInfo **info_p,
6639                                                        uint32_t *count_p)
6640 {
6641         int i;
6642         uint32_t version;
6643         struct spoolss_DriverInfo8 *driver;
6644         union spoolss_DriverInfo *info = NULL;
6645         uint32_t count = 0;
6646         WERROR result = WERR_OK;
6647         uint32_t num_drivers;
6648         const char **drivers;
6649
6650         *count_p = 0;
6651         *info_p = NULL;
6652
6653         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6654                 result = winreg_get_driver_list(mem_ctx, server_info,
6655                                                 architecture, version,
6656                                                 &num_drivers, &drivers);
6657                 if (!W_ERROR_IS_OK(result)) {
6658                         goto out;
6659                 }
6660                 DEBUG(4, ("we have:[%d] drivers in environment"
6661                           " [%s] and version [%d]\n",
6662                           num_drivers, architecture, version));
6663
6664                 if (num_drivers != 0) {
6665                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6666                                                     union spoolss_DriverInfo,
6667                                                     count + num_drivers);
6668                         if (!info) {
6669                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6670                                         "failed to enlarge driver info buffer!\n"));
6671                                 result = WERR_NOMEM;
6672                                 goto out;
6673                         }
6674                 }
6675
6676                 for (i = 0; i < num_drivers; i++) {
6677                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6678
6679                         result = winreg_get_driver(mem_ctx, server_info,
6680                                                    architecture, drivers[i],
6681                                                    version, &driver);
6682                         if (!W_ERROR_IS_OK(result)) {
6683                                 goto out;
6684                         }
6685
6686                         switch (level) {
6687                         case 1:
6688                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6689                                                                    driver, servername);
6690                                 break;
6691                         case 2:
6692                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6693                                                                    driver, servername);
6694                                 break;
6695                         case 3:
6696                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6697                                                                    driver, servername);
6698                                 break;
6699                         case 4:
6700                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6701                                                                    driver, servername);
6702                                 break;
6703                         case 5:
6704                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6705                                                                    driver, servername);
6706                                 break;
6707                         case 6:
6708                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6709                                                                    driver, servername);
6710                                 break;
6711                         case 8:
6712                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6713                                                                    driver, servername);
6714                                 break;
6715                         default:
6716                                 result = WERR_UNKNOWN_LEVEL;
6717                                 break;
6718                         }
6719
6720                         TALLOC_FREE(driver);
6721
6722                         if (!W_ERROR_IS_OK(result)) {
6723                                 goto out;
6724                         }
6725                 }
6726
6727                 count += num_drivers;
6728                 TALLOC_FREE(drivers);
6729         }
6730
6731  out:
6732         TALLOC_FREE(drivers);
6733
6734         if (!W_ERROR_IS_OK(result)) {
6735                 TALLOC_FREE(info);
6736                 return result;
6737         }
6738
6739         *info_p = info;
6740         *count_p = count;
6741
6742         return WERR_OK;
6743 }
6744
6745 /****************************************************************************
6746  Enumerates all printer drivers by level.
6747 ****************************************************************************/
6748
6749 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6750                                        struct auth_serversupplied_info *server_info,
6751                                        const char *servername,
6752                                        const char *architecture,
6753                                        uint32_t level,
6754                                        union spoolss_DriverInfo **info_p,
6755                                        uint32_t *count_p)
6756 {
6757         uint32_t a,i;
6758         WERROR result = WERR_OK;
6759
6760         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6761
6762                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6763
6764                         union spoolss_DriverInfo *info = NULL;
6765                         uint32_t count = 0;
6766
6767                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6768                                                                           server_info,
6769                                                                           servername,
6770                                                                           archi_table[a].long_archi,
6771                                                                           level,
6772                                                                           &info,
6773                                                                           &count);
6774                         if (!W_ERROR_IS_OK(result)) {
6775                                 continue;
6776                         }
6777
6778                         for (i=0; i < count; i++) {
6779                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6780                                              info[i], info_p, count_p);
6781                         }
6782                 }
6783
6784                 return result;
6785         }
6786
6787         return enumprinterdrivers_level_by_architecture(mem_ctx,
6788                                                         server_info,
6789                                                         servername,
6790                                                         architecture,
6791                                                         level,
6792                                                         info_p,
6793                                                         count_p);
6794 }
6795
6796 /****************************************************************
6797  _spoolss_EnumPrinterDrivers
6798 ****************************************************************/
6799
6800 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6801                                    struct spoolss_EnumPrinterDrivers *r)
6802 {
6803         const char *cservername;
6804         WERROR result;
6805
6806         /* that's an [in out] buffer */
6807
6808         if (!r->in.buffer && (r->in.offered != 0)) {
6809                 return WERR_INVALID_PARAM;
6810         }
6811
6812         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6813
6814         *r->out.needed = 0;
6815         *r->out.count = 0;
6816         *r->out.info = NULL;
6817
6818         cservername = canon_servername(r->in.server);
6819
6820         if (!is_myname_or_ipaddr(cservername)) {
6821                 return WERR_UNKNOWN_PRINTER_DRIVER;
6822         }
6823
6824         result = enumprinterdrivers_level(p->mem_ctx,
6825                                           p->server_info,
6826                                           cservername,
6827                                           r->in.environment,
6828                                           r->in.level,
6829                                           r->out.info,
6830                                           r->out.count);
6831         if (!W_ERROR_IS_OK(result)) {
6832                 return result;
6833         }
6834
6835         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6836                                                      spoolss_EnumPrinterDrivers, 
6837                                                      *r->out.info, r->in.level,
6838                                                      *r->out.count);
6839         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6840         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6841
6842         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6843 }
6844
6845 /****************************************************************
6846  _spoolss_EnumForms
6847 ****************************************************************/
6848
6849 WERROR _spoolss_EnumForms(pipes_struct *p,
6850                           struct spoolss_EnumForms *r)
6851 {
6852         WERROR result;
6853
6854         *r->out.count = 0;
6855         *r->out.needed = 0;
6856         *r->out.info = NULL;
6857
6858         /* that's an [in out] buffer */
6859
6860         if (!r->in.buffer && (r->in.offered != 0) ) {
6861                 return WERR_INVALID_PARAM;
6862         }
6863
6864         DEBUG(4,("_spoolss_EnumForms\n"));
6865         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6866         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6867
6868         switch (r->in.level) {
6869         case 1:
6870                 result = winreg_printer_enumforms1(p->mem_ctx,
6871                                                    p->server_info,
6872                                                    r->out.count,
6873                                                    r->out.info);
6874                 break;
6875         default:
6876                 result = WERR_UNKNOWN_LEVEL;
6877                 break;
6878         }
6879
6880         if (!W_ERROR_IS_OK(result)) {
6881                 return result;
6882         }
6883
6884         if (*r->out.count == 0) {
6885                 return WERR_NO_MORE_ITEMS;
6886         }
6887
6888         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6889                                                      spoolss_EnumForms, 
6890                                                      *r->out.info, r->in.level,
6891                                                      *r->out.count);
6892         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6893         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6894
6895         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6896 }
6897
6898 /****************************************************************
6899  _spoolss_GetForm
6900 ****************************************************************/
6901
6902 WERROR _spoolss_GetForm(pipes_struct *p,
6903                         struct spoolss_GetForm *r)
6904 {
6905         WERROR result;
6906
6907         /* that's an [in out] buffer */
6908
6909         if (!r->in.buffer && (r->in.offered != 0)) {
6910                 return WERR_INVALID_PARAM;
6911         }
6912
6913         DEBUG(4,("_spoolss_GetForm\n"));
6914         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6915         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6916
6917         switch (r->in.level) {
6918         case 1:
6919                 result = winreg_printer_getform1(p->mem_ctx,
6920                                                  p->server_info,
6921                                                  r->in.form_name,
6922                                                  &r->out.info->info1);
6923                 break;
6924         default:
6925                 result = WERR_UNKNOWN_LEVEL;
6926                 break;
6927         }
6928
6929         if (!W_ERROR_IS_OK(result)) {
6930                 TALLOC_FREE(r->out.info);
6931                 return result;
6932         }
6933
6934         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6935                                                r->out.info, r->in.level);
6936         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6937
6938         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6939 }
6940
6941 /****************************************************************************
6942 ****************************************************************************/
6943
6944 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6945                           struct spoolss_PortInfo1 *r,
6946                           const char *name)
6947 {
6948         r->port_name = talloc_strdup(mem_ctx, name);
6949         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6950
6951         return WERR_OK;
6952 }
6953
6954 /****************************************************************************
6955  TODO: This probably needs distinguish between TCP/IP and Local ports
6956  somehow.
6957 ****************************************************************************/
6958
6959 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6960                           struct spoolss_PortInfo2 *r,
6961                           const char *name)
6962 {
6963         r->port_name = talloc_strdup(mem_ctx, name);
6964         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6965
6966         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6967         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6968
6969         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6970         W_ERROR_HAVE_NO_MEMORY(r->description);
6971
6972         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6973         r->reserved = 0;
6974
6975         return WERR_OK;
6976 }
6977
6978
6979 /****************************************************************************
6980  wrapper around the enumer ports command
6981 ****************************************************************************/
6982
6983 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6984 {
6985         char *cmd = lp_enumports_cmd();
6986         char **qlines = NULL;
6987         char *command = NULL;
6988         int numlines;
6989         int ret;
6990         int fd;
6991
6992         *count = 0;
6993         *lines = NULL;
6994
6995         /* if no hook then just fill in the default port */
6996
6997         if ( !*cmd ) {
6998                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6999                         return WERR_NOMEM;
7000                 }
7001                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7002                         TALLOC_FREE(qlines);
7003                         return WERR_NOMEM;
7004                 }
7005                 qlines[1] = NULL;
7006                 numlines = 1;
7007         }
7008         else {
7009                 /* we have a valid enumport command */
7010
7011                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7012                 if (!command) {
7013                         return WERR_NOMEM;
7014                 }
7015
7016                 DEBUG(10,("Running [%s]\n", command));
7017                 ret = smbrun(command, &fd);
7018                 DEBUG(10,("Returned [%d]\n", ret));
7019                 TALLOC_FREE(command);
7020                 if (ret != 0) {
7021                         if (fd != -1) {
7022                                 close(fd);
7023                         }
7024                         return WERR_ACCESS_DENIED;
7025                 }
7026
7027                 numlines = 0;
7028                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7029                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7030                 close(fd);
7031         }
7032
7033         *count = numlines;
7034         *lines = qlines;
7035
7036         return WERR_OK;
7037 }
7038
7039 /****************************************************************************
7040  enumports level 1.
7041 ****************************************************************************/
7042
7043 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7044                                 union spoolss_PortInfo **info_p,
7045                                 uint32_t *count)
7046 {
7047         union spoolss_PortInfo *info = NULL;
7048         int i=0;
7049         WERROR result = WERR_OK;
7050         char **qlines = NULL;
7051         int numlines = 0;
7052
7053         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7054         if (!W_ERROR_IS_OK(result)) {
7055                 goto out;
7056         }
7057
7058         if (numlines) {
7059                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7060                 if (!info) {
7061                         DEBUG(10,("Returning WERR_NOMEM\n"));
7062                         result = WERR_NOMEM;
7063                         goto out;
7064                 }
7065
7066                 for (i=0; i<numlines; i++) {
7067                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7068                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7069                         if (!W_ERROR_IS_OK(result)) {
7070                                 goto out;
7071                         }
7072                 }
7073         }
7074         TALLOC_FREE(qlines);
7075
7076 out:
7077         if (!W_ERROR_IS_OK(result)) {
7078                 TALLOC_FREE(info);
7079                 TALLOC_FREE(qlines);
7080                 *count = 0;
7081                 *info_p = NULL;
7082                 return result;
7083         }
7084
7085         *info_p = info;
7086         *count = numlines;
7087
7088         return WERR_OK;
7089 }
7090
7091 /****************************************************************************
7092  enumports level 2.
7093 ****************************************************************************/
7094
7095 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7096                                 union spoolss_PortInfo **info_p,
7097                                 uint32_t *count)
7098 {
7099         union spoolss_PortInfo *info = NULL;
7100         int i=0;
7101         WERROR result = WERR_OK;
7102         char **qlines = NULL;
7103         int numlines = 0;
7104
7105         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7106         if (!W_ERROR_IS_OK(result)) {
7107                 goto out;
7108         }
7109
7110         if (numlines) {
7111                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7112                 if (!info) {
7113                         DEBUG(10,("Returning WERR_NOMEM\n"));
7114                         result = WERR_NOMEM;
7115                         goto out;
7116                 }
7117
7118                 for (i=0; i<numlines; i++) {
7119                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7120                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7121                         if (!W_ERROR_IS_OK(result)) {
7122                                 goto out;
7123                         }
7124                 }
7125         }
7126         TALLOC_FREE(qlines);
7127
7128 out:
7129         if (!W_ERROR_IS_OK(result)) {
7130                 TALLOC_FREE(info);
7131                 TALLOC_FREE(qlines);
7132                 *count = 0;
7133                 *info_p = NULL;
7134                 return result;
7135         }
7136
7137         *info_p = info;
7138         *count = numlines;
7139
7140         return WERR_OK;
7141 }
7142
7143 /****************************************************************
7144  _spoolss_EnumPorts
7145 ****************************************************************/
7146
7147 WERROR _spoolss_EnumPorts(pipes_struct *p,
7148                           struct spoolss_EnumPorts *r)
7149 {
7150         WERROR result;
7151
7152         /* that's an [in out] buffer */
7153
7154         if (!r->in.buffer && (r->in.offered != 0)) {
7155                 return WERR_INVALID_PARAM;
7156         }
7157
7158         DEBUG(4,("_spoolss_EnumPorts\n"));
7159
7160         *r->out.count = 0;
7161         *r->out.needed = 0;
7162         *r->out.info = NULL;
7163
7164         switch (r->in.level) {
7165         case 1:
7166                 result = enumports_level_1(p->mem_ctx, r->out.info,
7167                                            r->out.count);
7168                 break;
7169         case 2:
7170                 result = enumports_level_2(p->mem_ctx, r->out.info,
7171                                            r->out.count);
7172                 break;
7173         default:
7174                 return WERR_UNKNOWN_LEVEL;
7175         }
7176
7177         if (!W_ERROR_IS_OK(result)) {
7178                 return result;
7179         }
7180
7181         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7182                                                      spoolss_EnumPorts, 
7183                                                      *r->out.info, r->in.level,
7184                                                      *r->out.count);
7185         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7186         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7187
7188         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7189 }
7190
7191 /****************************************************************************
7192 ****************************************************************************/
7193
7194 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7195                                            const char *server,
7196                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7197                                            struct spoolss_DeviceMode *devmode,
7198                                            struct security_descriptor *secdesc,
7199                                            struct spoolss_UserLevelCtr *user_ctr,
7200                                            struct policy_handle *handle)
7201 {
7202         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7203         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7204         int     snum;
7205         WERROR err = WERR_OK;
7206
7207         /* samba does not have a concept of local, non-shared printers yet, so
7208          * make sure we always setup sharename - gd */
7209         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7210             (info2->printername != NULL && info2->printername[0] != '\0')) {
7211                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7212                         "no sharename has been set, setting printername %s as sharename\n",
7213                         info2->printername));
7214                 info2->sharename = info2->printername;
7215         }
7216
7217         /* check to see if the printer already exists */
7218         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7219                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7220                         info2->sharename));
7221                 return WERR_PRINTER_ALREADY_EXISTS;
7222         }
7223
7224         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7225                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7226                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7227                                 info2->printername));
7228                         return WERR_PRINTER_ALREADY_EXISTS;
7229                 }
7230         }
7231
7232         /* validate printer info struct */
7233         if (!info2->printername || strlen(info2->printername) == 0) {
7234                 return WERR_INVALID_PRINTER_NAME;
7235         }
7236         if (!info2->portname || strlen(info2->portname) == 0) {
7237                 return WERR_UNKNOWN_PORT;
7238         }
7239         if (!info2->drivername || strlen(info2->drivername) == 0) {
7240                 return WERR_UNKNOWN_PRINTER_DRIVER;
7241         }
7242         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7243                 return WERR_UNKNOWN_PRINTPROCESSOR;
7244         }
7245
7246         /* FIXME!!!  smbd should check to see if the driver is installed before
7247            trying to add a printer like this  --jerry */
7248
7249         if (*lp_addprinter_cmd() ) {
7250                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7251                                        info2) ) {
7252                         return WERR_ACCESS_DENIED;
7253                 }
7254         } else {
7255                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7256                         "smb.conf parameter \"addprinter command\" is defined. This"
7257                         "parameter must exist for this call to succeed\n",
7258                         info2->sharename ));
7259         }
7260
7261         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7262                 return WERR_ACCESS_DENIED;
7263         }
7264
7265         /* you must be a printer admin to add a new printer */
7266         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7267                 return WERR_ACCESS_DENIED;
7268         }
7269
7270         /*
7271          * Do sanity check on the requested changes for Samba.
7272          */
7273
7274         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7275                 return WERR_INVALID_PARAM;
7276         }
7277
7278         if (devmode == NULL) {
7279                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7280         }
7281
7282         update_dsspooler(p->mem_ctx,
7283                          p->server_info,
7284                          0,
7285                          info2,
7286                          NULL);
7287
7288         err = winreg_update_printer(p->mem_ctx,
7289                                     p->server_info,
7290                                     info2->sharename,
7291                                     info2_mask,
7292                                     info2,
7293                                     devmode,
7294                                     secdesc);
7295         if (!W_ERROR_IS_OK(err)) {
7296                 return err;
7297         }
7298
7299         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7300                 /* Handle open failed - remove addition. */
7301                 ZERO_STRUCTP(handle);
7302                 return WERR_ACCESS_DENIED;
7303         }
7304
7305         return WERR_OK;
7306 }
7307
7308 /****************************************************************
7309  _spoolss_AddPrinterEx
7310 ****************************************************************/
7311
7312 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7313                              struct spoolss_AddPrinterEx *r)
7314 {
7315         switch (r->in.info_ctr->level) {
7316         case 1:
7317                 /* we don't handle yet */
7318                 /* but I know what to do ... */
7319                 return WERR_UNKNOWN_LEVEL;
7320         case 2:
7321                 return spoolss_addprinterex_level_2(p, r->in.server,
7322                                                     r->in.info_ctr,
7323                                                     r->in.devmode_ctr->devmode,
7324                                                     r->in.secdesc_ctr->sd,
7325                                                     r->in.userlevel_ctr,
7326                                                     r->out.handle);
7327         default:
7328                 return WERR_UNKNOWN_LEVEL;
7329         }
7330 }
7331
7332 /****************************************************************
7333  _spoolss_AddPrinter
7334 ****************************************************************/
7335
7336 WERROR _spoolss_AddPrinter(pipes_struct *p,
7337                            struct spoolss_AddPrinter *r)
7338 {
7339         struct spoolss_AddPrinterEx a;
7340         struct spoolss_UserLevelCtr userlevel_ctr;
7341
7342         ZERO_STRUCT(userlevel_ctr);
7343
7344         userlevel_ctr.level = 1;
7345
7346         a.in.server             = r->in.server;
7347         a.in.info_ctr           = r->in.info_ctr;
7348         a.in.devmode_ctr        = r->in.devmode_ctr;
7349         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7350         a.in.userlevel_ctr      = &userlevel_ctr;
7351         a.out.handle            = r->out.handle;
7352
7353         return _spoolss_AddPrinterEx(p, &a);
7354 }
7355
7356 /****************************************************************
7357  _spoolss_AddPrinterDriverEx
7358 ****************************************************************/
7359
7360 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7361                                    struct spoolss_AddPrinterDriverEx *r)
7362 {
7363         WERROR err = WERR_OK;
7364         const char *driver_name = NULL;
7365         uint32_t version;
7366         const char *fn;
7367
7368         switch (p->opnum) {
7369                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7370                         fn = "_spoolss_AddPrinterDriver";
7371                         break;
7372                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7373                         fn = "_spoolss_AddPrinterDriverEx";
7374                         break;
7375                 default:
7376                         return WERR_INVALID_PARAM;
7377         }
7378
7379         /*
7380          * we only support the semantics of AddPrinterDriver()
7381          * i.e. only copy files that are newer than existing ones
7382          */
7383
7384         if (r->in.flags == 0) {
7385                 return WERR_INVALID_PARAM;
7386         }
7387
7388         if (r->in.flags != APD_COPY_NEW_FILES) {
7389                 return WERR_ACCESS_DENIED;
7390         }
7391
7392         /* FIXME */
7393         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7394                 /* Clever hack from Martin Zielinski <mz@seh.de>
7395                  * to allow downgrade from level 8 (Vista).
7396                  */
7397                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7398                         r->in.info_ctr->level));
7399                 return WERR_UNKNOWN_LEVEL;
7400         }
7401
7402         DEBUG(5,("Cleaning driver's information\n"));
7403         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7404         if (!W_ERROR_IS_OK(err))
7405                 goto done;
7406
7407         DEBUG(5,("Moving driver to final destination\n"));
7408         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7409                                                               &err)) ) {
7410                 goto done;
7411         }
7412
7413         err = winreg_add_driver(p->mem_ctx, p->server_info,
7414                                 r->in.info_ctr, &driver_name, &version);
7415         if (!W_ERROR_IS_OK(err)) {
7416                 goto done;
7417         }
7418
7419         /*
7420          * I think this is where he DrvUpgradePrinter() hook would be
7421          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7422          * server.  Right now, we just need to send ourselves a message
7423          * to update each printer bound to this driver.   --jerry
7424          */
7425
7426         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7427                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7428                         fn, driver_name));
7429         }
7430
7431 done:
7432         return err;
7433 }
7434
7435 /****************************************************************
7436  _spoolss_AddPrinterDriver
7437 ****************************************************************/
7438
7439 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7440                                  struct spoolss_AddPrinterDriver *r)
7441 {
7442         struct spoolss_AddPrinterDriverEx a;
7443
7444         switch (r->in.info_ctr->level) {
7445         case 2:
7446         case 3:
7447         case 4:
7448         case 5:
7449                 break;
7450         default:
7451                 return WERR_UNKNOWN_LEVEL;
7452         }
7453
7454         a.in.servername         = r->in.servername;
7455         a.in.info_ctr           = r->in.info_ctr;
7456         a.in.flags              = APD_COPY_NEW_FILES;
7457
7458         return _spoolss_AddPrinterDriverEx(p, &a);
7459 }
7460
7461 /****************************************************************************
7462 ****************************************************************************/
7463
7464 struct _spoolss_paths {
7465         int type;
7466         const char *share;
7467         const char *dir;
7468 };
7469
7470 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7471
7472 static const struct _spoolss_paths spoolss_paths[]= {
7473         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7474         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7475 };
7476
7477 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7478                                           const char *servername,
7479                                           const char *environment,
7480                                           int component,
7481                                           char **path)
7482 {
7483         const char *pservername = NULL;
7484         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7485         const char *short_archi;
7486
7487         *path = NULL;
7488
7489         /* environment may be empty */
7490         if (environment && strlen(environment)) {
7491                 long_archi = environment;
7492         }
7493
7494         /* servername may be empty */
7495         if (servername && strlen(servername)) {
7496                 pservername = canon_servername(servername);
7497
7498                 if (!is_myname_or_ipaddr(pservername)) {
7499                         return WERR_INVALID_PARAM;
7500                 }
7501         }
7502
7503         if (!(short_archi = get_short_archi(long_archi))) {
7504                 return WERR_INVALID_ENVIRONMENT;
7505         }
7506
7507         switch (component) {
7508         case SPOOLSS_PRTPROCS_PATH:
7509         case SPOOLSS_DRIVER_PATH:
7510                 if (pservername) {
7511                         *path = talloc_asprintf(mem_ctx,
7512                                         "\\\\%s\\%s\\%s",
7513                                         pservername,
7514                                         spoolss_paths[component].share,
7515                                         short_archi);
7516                 } else {
7517                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7518                                         SPOOLSS_DEFAULT_SERVER_PATH,
7519                                         spoolss_paths[component].dir,
7520                                         short_archi);
7521                 }
7522                 break;
7523         default:
7524                 return WERR_INVALID_PARAM;
7525         }
7526
7527         if (!*path) {
7528                 return WERR_NOMEM;
7529         }
7530
7531         return WERR_OK;
7532 }
7533
7534 /****************************************************************************
7535 ****************************************************************************/
7536
7537 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7538                                           const char *servername,
7539                                           const char *environment,
7540                                           struct spoolss_DriverDirectoryInfo1 *r)
7541 {
7542         WERROR werr;
7543         char *path = NULL;
7544
7545         werr = compose_spoolss_server_path(mem_ctx,
7546                                            servername,
7547                                            environment,
7548                                            SPOOLSS_DRIVER_PATH,
7549                                            &path);
7550         if (!W_ERROR_IS_OK(werr)) {
7551                 return werr;
7552         }
7553
7554         DEBUG(4,("printer driver directory: [%s]\n", path));
7555
7556         r->directory_name = path;
7557
7558         return WERR_OK;
7559 }
7560
7561 /****************************************************************
7562  _spoolss_GetPrinterDriverDirectory
7563 ****************************************************************/
7564
7565 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7566                                           struct spoolss_GetPrinterDriverDirectory *r)
7567 {
7568         WERROR werror;
7569
7570         /* that's an [in out] buffer */
7571
7572         if (!r->in.buffer && (r->in.offered != 0)) {
7573                 return WERR_INVALID_PARAM;
7574         }
7575
7576         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7577                 r->in.level));
7578
7579         *r->out.needed = 0;
7580
7581         /* r->in.level is ignored */
7582
7583         werror = getprinterdriverdir_level_1(p->mem_ctx,
7584                                              r->in.server,
7585                                              r->in.environment,
7586                                              &r->out.info->info1);
7587         if (!W_ERROR_IS_OK(werror)) {
7588                 TALLOC_FREE(r->out.info);
7589                 return werror;
7590         }
7591
7592         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7593                                                r->out.info, r->in.level);
7594         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7595
7596         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7597 }
7598
7599 /****************************************************************
7600  _spoolss_EnumPrinterData
7601 ****************************************************************/
7602
7603 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7604                                 struct spoolss_EnumPrinterData *r)
7605 {
7606         WERROR result;
7607         struct spoolss_EnumPrinterDataEx r2;
7608         uint32_t count;
7609         struct spoolss_PrinterEnumValues *info, *val = NULL;
7610         uint32_t needed;
7611
7612         r2.in.handle    = r->in.handle;
7613         r2.in.key_name  = "PrinterDriverData";
7614         r2.in.offered   = 0;
7615         r2.out.count    = &count;
7616         r2.out.info     = &info;
7617         r2.out.needed   = &needed;
7618
7619         result = _spoolss_EnumPrinterDataEx(p, &r2);
7620         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7621                 r2.in.offered = needed;
7622                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7623         }
7624         if (!W_ERROR_IS_OK(result)) {
7625                 return result;
7626         }
7627
7628         /*
7629          * The NT machine wants to know the biggest size of value and data
7630          *
7631          * cf: MSDN EnumPrinterData remark section
7632          */
7633
7634         if (!r->in.value_offered && !r->in.data_offered) {
7635                 uint32_t biggest_valuesize = 0;
7636                 uint32_t biggest_datasize = 0;
7637                 int i, name_length;
7638
7639                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7640
7641                 for (i=0; i<count; i++) {
7642
7643                         name_length = strlen(info[i].value_name);
7644                         if (strlen(info[i].value_name) > biggest_valuesize) {
7645                                 biggest_valuesize = name_length;
7646                         }
7647
7648                         if (info[i].data_length > biggest_datasize) {
7649                                 biggest_datasize = info[i].data_length;
7650                         }
7651
7652                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7653                                 biggest_datasize));
7654                 }
7655
7656                 /* the value is an UNICODE string but real_value_size is the length
7657                    in bytes including the trailing 0 */
7658
7659                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7660                 *r->out.data_needed  = biggest_datasize;
7661
7662                 DEBUG(6,("final values: [%d], [%d]\n",
7663                         *r->out.value_needed, *r->out.data_needed));
7664
7665                 return WERR_OK;
7666         }
7667
7668         if (r->in.enum_index < count) {
7669                 val = &info[r->in.enum_index];
7670         }
7671
7672         if (val == NULL) {
7673                 /* out_value should default to "" or else NT4 has
7674                    problems unmarshalling the response */
7675
7676                 if (r->in.value_offered) {
7677                         *r->out.value_needed = 1;
7678                         r->out.value_name = talloc_strdup(r, "");
7679                         if (!r->out.value_name) {
7680                                 return WERR_NOMEM;
7681                         }
7682                 } else {
7683                         r->out.value_name = NULL;
7684                         *r->out.value_needed = 0;
7685                 }
7686
7687                 /* the data is counted in bytes */
7688
7689                 *r->out.data_needed = r->in.data_offered;
7690
7691                 result = WERR_NO_MORE_ITEMS;
7692         } else {
7693                 /*
7694                  * the value is:
7695                  * - counted in bytes in the request
7696                  * - counted in UNICODE chars in the max reply
7697                  * - counted in bytes in the real size
7698                  *
7699                  * take a pause *before* coding not *during* coding
7700                  */
7701
7702                 /* name */
7703                 if (r->in.value_offered) {
7704                         r->out.value_name = talloc_strdup(r, val->value_name);
7705                         if (!r->out.value_name) {
7706                                 return WERR_NOMEM;
7707                         }
7708                         *r->out.value_needed = val->value_name_len;
7709                 } else {
7710                         r->out.value_name = NULL;
7711                         *r->out.value_needed = 0;
7712                 }
7713
7714                 /* type */
7715
7716                 *r->out.type = val->type;
7717
7718                 /* data - counted in bytes */
7719
7720                 /*
7721                  * See the section "Dynamically Typed Query Parameters"
7722                  * in MS-RPRN.
7723                  */
7724
7725                 if (r->out.data && val->data && val->data->data &&
7726                                 val->data_length && r->in.data_offered) {
7727                         memcpy(r->out.data, val->data->data,
7728                                 MIN(val->data_length,r->in.data_offered));
7729                 }
7730
7731                 *r->out.data_needed = val->data_length;
7732
7733                 result = WERR_OK;
7734         }
7735
7736         return result;
7737 }
7738
7739 /****************************************************************
7740  _spoolss_SetPrinterData
7741 ****************************************************************/
7742
7743 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7744                                struct spoolss_SetPrinterData *r)
7745 {
7746         struct spoolss_SetPrinterDataEx r2;
7747
7748         r2.in.handle            = r->in.handle;
7749         r2.in.key_name          = "PrinterDriverData";
7750         r2.in.value_name        = r->in.value_name;
7751         r2.in.type              = r->in.type;
7752         r2.in.data              = r->in.data;
7753         r2.in.offered           = r->in.offered;
7754
7755         return _spoolss_SetPrinterDataEx(p, &r2);
7756 }
7757
7758 /****************************************************************
7759  _spoolss_ResetPrinter
7760 ****************************************************************/
7761
7762 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7763                              struct spoolss_ResetPrinter *r)
7764 {
7765         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7766         int             snum;
7767
7768         DEBUG(5,("_spoolss_ResetPrinter\n"));
7769
7770         /*
7771          * All we do is to check to see if the handle and queue is valid.
7772          * This call really doesn't mean anything to us because we only
7773          * support RAW printing.   --jerry
7774          */
7775
7776         if (!Printer) {
7777                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7778                         OUR_HANDLE(r->in.handle)));
7779                 return WERR_BADFID;
7780         }
7781
7782         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7783                 return WERR_BADFID;
7784
7785
7786         /* blindly return success */
7787         return WERR_OK;
7788 }
7789
7790 /****************************************************************
7791  _spoolss_DeletePrinterData
7792 ****************************************************************/
7793
7794 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7795                                   struct spoolss_DeletePrinterData *r)
7796 {
7797         struct spoolss_DeletePrinterDataEx r2;
7798
7799         r2.in.handle            = r->in.handle;
7800         r2.in.key_name          = "PrinterDriverData";
7801         r2.in.value_name        = r->in.value_name;
7802
7803         return _spoolss_DeletePrinterDataEx(p, &r2);
7804 }
7805
7806 /****************************************************************
7807  _spoolss_AddForm
7808 ****************************************************************/
7809
7810 WERROR _spoolss_AddForm(pipes_struct *p,
7811                         struct spoolss_AddForm *r)
7812 {
7813         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7814         int snum = -1;
7815         WERROR status = WERR_OK;
7816         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7817
7818         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7819
7820         DEBUG(5,("_spoolss_AddForm\n"));
7821
7822         if (!Printer) {
7823                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7824                         OUR_HANDLE(r->in.handle)));
7825                 return WERR_BADFID;
7826         }
7827
7828         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7829            and not a printer admin, then fail */
7830
7831         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7832              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7833              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7834                                           p->server_info->info3->base.domain.string,
7835                                           NULL,
7836                                           p->server_info->ptok,
7837                                           lp_printer_admin(snum))) {
7838                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7839                 return WERR_ACCESS_DENIED;
7840         }
7841
7842         switch (form->flags) {
7843         case SPOOLSS_FORM_USER:
7844         case SPOOLSS_FORM_BUILTIN:
7845         case SPOOLSS_FORM_PRINTER:
7846                 break;
7847         default:
7848                 return WERR_INVALID_PARAM;
7849         }
7850
7851         status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7852         if (!W_ERROR_IS_OK(status)) {
7853                 return status;
7854         }
7855
7856         /*
7857          * ChangeID must always be set if this is a printer
7858          */
7859         if (Printer->printer_type == SPLHND_PRINTER) {
7860                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7861                         return WERR_BADFID;
7862                 }
7863
7864                 status = winreg_printer_update_changeid(p->mem_ctx,
7865                                                         p->server_info,
7866                                                         lp_const_servicename(snum));
7867                 if (!W_ERROR_IS_OK(status)) {
7868                         return status;
7869                 }
7870         }
7871
7872         return status;
7873 }
7874
7875 /****************************************************************
7876  _spoolss_DeleteForm
7877 ****************************************************************/
7878
7879 WERROR _spoolss_DeleteForm(pipes_struct *p,
7880                            struct spoolss_DeleteForm *r)
7881 {
7882         const char *form_name = r->in.form_name;
7883         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7884         int snum = -1;
7885         WERROR status = WERR_OK;
7886         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7887
7888         DEBUG(5,("_spoolss_DeleteForm\n"));
7889
7890         if (!Printer) {
7891                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7892                         OUR_HANDLE(r->in.handle)));
7893                 return WERR_BADFID;
7894         }
7895
7896         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7897              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7898              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7899                                           p->server_info->info3->base.domain.string,
7900                                           NULL,
7901                                           p->server_info->ptok,
7902                                           lp_printer_admin(snum))) {
7903                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7904                 return WERR_ACCESS_DENIED;
7905         }
7906
7907         status = winreg_printer_deleteform1(p->mem_ctx,
7908                                             p->server_info,
7909                                             form_name);
7910         if (!W_ERROR_IS_OK(status)) {
7911                 return status;
7912         }
7913
7914         /*
7915          * ChangeID must always be set if this is a printer
7916          */
7917         if (Printer->printer_type == SPLHND_PRINTER) {
7918                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7919                         return WERR_BADFID;
7920                 }
7921
7922                 status = winreg_printer_update_changeid(p->mem_ctx,
7923                                                         p->server_info,
7924                                                         lp_const_servicename(snum));
7925                 if (!W_ERROR_IS_OK(status)) {
7926                         return status;
7927                 }
7928         }
7929
7930         return status;
7931 }
7932
7933 /****************************************************************
7934  _spoolss_SetForm
7935 ****************************************************************/
7936
7937 WERROR _spoolss_SetForm(pipes_struct *p,
7938                         struct spoolss_SetForm *r)
7939 {
7940         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7941         const char *form_name = r->in.form_name;
7942         int snum = -1;
7943         WERROR status = WERR_OK;
7944         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7945
7946         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7947
7948         DEBUG(5,("_spoolss_SetForm\n"));
7949
7950         if (!Printer) {
7951                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7952                         OUR_HANDLE(r->in.handle)));
7953                 return WERR_BADFID;
7954         }
7955
7956         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7957            and not a printer admin, then fail */
7958
7959         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7960              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7961              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7962                                           p->server_info->info3->base.domain.string,
7963                                           NULL,
7964                                           p->server_info->ptok,
7965                                           lp_printer_admin(snum))) {
7966                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7967                 return WERR_ACCESS_DENIED;
7968         }
7969
7970         status = winreg_printer_setform1(p->mem_ctx,
7971                                          p->server_info,
7972                                          form_name,
7973                                          form);
7974         if (!W_ERROR_IS_OK(status)) {
7975                 return status;
7976         }
7977
7978         /*
7979          * ChangeID must always be set if this is a printer
7980          */
7981         if (Printer->printer_type == SPLHND_PRINTER) {
7982                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7983                         return WERR_BADFID;
7984                 }
7985
7986                 status = winreg_printer_update_changeid(p->mem_ctx,
7987                                                         p->server_info,
7988                                                         lp_const_servicename(snum));
7989                 if (!W_ERROR_IS_OK(status)) {
7990                         return status;
7991                 }
7992         }
7993
7994         return status;
7995 }
7996
7997 /****************************************************************************
7998  fill_print_processor1
7999 ****************************************************************************/
8000
8001 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8002                                     struct spoolss_PrintProcessorInfo1 *r,
8003                                     const char *print_processor_name)
8004 {
8005         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8006         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8007
8008         return WERR_OK;
8009 }
8010
8011 /****************************************************************************
8012  enumprintprocessors level 1.
8013 ****************************************************************************/
8014
8015 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8016                                           union spoolss_PrintProcessorInfo **info_p,
8017                                           uint32_t *count)
8018 {
8019         union spoolss_PrintProcessorInfo *info;
8020         WERROR result;
8021
8022         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8023         W_ERROR_HAVE_NO_MEMORY(info);
8024
8025         *count = 1;
8026
8027         result = fill_print_processor1(info, &info[0].info1, "winprint");
8028         if (!W_ERROR_IS_OK(result)) {
8029                 goto out;
8030         }
8031
8032  out:
8033         if (!W_ERROR_IS_OK(result)) {
8034                 TALLOC_FREE(info);
8035                 *count = 0;
8036                 return result;
8037         }
8038
8039         *info_p = info;
8040
8041         return WERR_OK;
8042 }
8043
8044 /****************************************************************
8045  _spoolss_EnumPrintProcessors
8046 ****************************************************************/
8047
8048 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8049                                     struct spoolss_EnumPrintProcessors *r)
8050 {
8051         WERROR result;
8052
8053         /* that's an [in out] buffer */
8054
8055         if (!r->in.buffer && (r->in.offered != 0)) {
8056                 return WERR_INVALID_PARAM;
8057         }
8058
8059         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8060
8061         /*
8062          * Enumerate the print processors ...
8063          *
8064          * Just reply with "winprint", to keep NT happy
8065          * and I can use my nice printer checker.
8066          */
8067
8068         *r->out.count = 0;
8069         *r->out.needed = 0;
8070         *r->out.info = NULL;
8071
8072         switch (r->in.level) {
8073         case 1:
8074                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8075                                                      r->out.count);
8076                 break;
8077         default:
8078                 return WERR_UNKNOWN_LEVEL;
8079         }
8080
8081         if (!W_ERROR_IS_OK(result)) {
8082                 return result;
8083         }
8084
8085         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8086                                                      spoolss_EnumPrintProcessors,
8087                                                      *r->out.info, r->in.level,
8088                                                      *r->out.count);
8089         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8090         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8091
8092         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8093 }
8094
8095 /****************************************************************************
8096  fill_printprocdatatype1
8097 ****************************************************************************/
8098
8099 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8100                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8101                                       const char *name_array)
8102 {
8103         r->name_array = talloc_strdup(mem_ctx, name_array);
8104         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8105
8106         return WERR_OK;
8107 }
8108
8109 /****************************************************************************
8110  enumprintprocdatatypes level 1.
8111 ****************************************************************************/
8112
8113 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8114                                              union spoolss_PrintProcDataTypesInfo **info_p,
8115                                              uint32_t *count)
8116 {
8117         WERROR result;
8118         union spoolss_PrintProcDataTypesInfo *info;
8119
8120         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8121         W_ERROR_HAVE_NO_MEMORY(info);
8122
8123         *count = 1;
8124
8125         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8126         if (!W_ERROR_IS_OK(result)) {
8127                 goto out;
8128         }
8129
8130  out:
8131         if (!W_ERROR_IS_OK(result)) {
8132                 TALLOC_FREE(info);
8133                 *count = 0;
8134                 return result;
8135         }
8136
8137         *info_p = info;
8138
8139         return WERR_OK;
8140 }
8141
8142 /****************************************************************
8143  _spoolss_EnumPrintProcDataTypes
8144 ****************************************************************/
8145
8146 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8147                                        struct spoolss_EnumPrintProcDataTypes *r)
8148 {
8149         WERROR result;
8150
8151         /* that's an [in out] buffer */
8152
8153         if (!r->in.buffer && (r->in.offered != 0)) {
8154                 return WERR_INVALID_PARAM;
8155         }
8156
8157         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8158
8159         *r->out.count = 0;
8160         *r->out.needed = 0;
8161         *r->out.info = NULL;
8162
8163         switch (r->in.level) {
8164         case 1:
8165                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8166                                                         r->out.count);
8167                 break;
8168         default:
8169                 return WERR_UNKNOWN_LEVEL;
8170         }
8171
8172         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8173                                                      spoolss_EnumPrintProcDataTypes, 
8174                                                      *r->out.info, r->in.level,
8175                                                      *r->out.count);
8176         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8177         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8178
8179         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8180 }
8181
8182 /****************************************************************************
8183  fill_monitor_1
8184 ****************************************************************************/
8185
8186 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8187                              struct spoolss_MonitorInfo1 *r,
8188                              const char *monitor_name)
8189 {
8190         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8191         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8192
8193         return WERR_OK;
8194 }
8195
8196 /****************************************************************************
8197  fill_monitor_2
8198 ****************************************************************************/
8199
8200 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8201                              struct spoolss_MonitorInfo2 *r,
8202                              const char *monitor_name,
8203                              const char *environment,
8204                              const char *dll_name)
8205 {
8206         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8207         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8208         r->environment                  = talloc_strdup(mem_ctx, environment);
8209         W_ERROR_HAVE_NO_MEMORY(r->environment);
8210         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8211         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8212
8213         return WERR_OK;
8214 }
8215
8216 /****************************************************************************
8217  enumprintmonitors level 1.
8218 ****************************************************************************/
8219
8220 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8221                                         union spoolss_MonitorInfo **info_p,
8222                                         uint32_t *count)
8223 {
8224         union spoolss_MonitorInfo *info;
8225         WERROR result = WERR_OK;
8226
8227         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8228         W_ERROR_HAVE_NO_MEMORY(info);
8229
8230         *count = 2;
8231
8232         result = fill_monitor_1(info, &info[0].info1,
8233                                 SPL_LOCAL_PORT);
8234         if (!W_ERROR_IS_OK(result)) {
8235                 goto out;
8236         }
8237
8238         result = fill_monitor_1(info, &info[1].info1,
8239                                 SPL_TCPIP_PORT);
8240         if (!W_ERROR_IS_OK(result)) {
8241                 goto out;
8242         }
8243
8244 out:
8245         if (!W_ERROR_IS_OK(result)) {
8246                 TALLOC_FREE(info);
8247                 *count = 0;
8248                 return result;
8249         }
8250
8251         *info_p = info;
8252
8253         return WERR_OK;
8254 }
8255
8256 /****************************************************************************
8257  enumprintmonitors level 2.
8258 ****************************************************************************/
8259
8260 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8261                                         union spoolss_MonitorInfo **info_p,
8262                                         uint32_t *count)
8263 {
8264         union spoolss_MonitorInfo *info;
8265         WERROR result = WERR_OK;
8266
8267         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8268         W_ERROR_HAVE_NO_MEMORY(info);
8269
8270         *count = 2;
8271
8272         result = fill_monitor_2(info, &info[0].info2,
8273                                 SPL_LOCAL_PORT,
8274                                 "Windows NT X86", /* FIXME */
8275                                 "localmon.dll");
8276         if (!W_ERROR_IS_OK(result)) {
8277                 goto out;
8278         }
8279
8280         result = fill_monitor_2(info, &info[1].info2,
8281                                 SPL_TCPIP_PORT,
8282                                 "Windows NT X86", /* FIXME */
8283                                 "tcpmon.dll");
8284         if (!W_ERROR_IS_OK(result)) {
8285                 goto out;
8286         }
8287
8288 out:
8289         if (!W_ERROR_IS_OK(result)) {
8290                 TALLOC_FREE(info);
8291                 *count = 0;
8292                 return result;
8293         }
8294
8295         *info_p = info;
8296
8297         return WERR_OK;
8298 }
8299
8300 /****************************************************************
8301  _spoolss_EnumMonitors
8302 ****************************************************************/
8303
8304 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8305                              struct spoolss_EnumMonitors *r)
8306 {
8307         WERROR result;
8308
8309         /* that's an [in out] buffer */
8310
8311         if (!r->in.buffer && (r->in.offered != 0)) {
8312                 return WERR_INVALID_PARAM;
8313         }
8314
8315         DEBUG(5,("_spoolss_EnumMonitors\n"));
8316
8317         /*
8318          * Enumerate the print monitors ...
8319          *
8320          * Just reply with "Local Port", to keep NT happy
8321          * and I can use my nice printer checker.
8322          */
8323
8324         *r->out.count = 0;
8325         *r->out.needed = 0;
8326         *r->out.info = NULL;
8327
8328         switch (r->in.level) {
8329         case 1:
8330                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8331                                                    r->out.count);
8332                 break;
8333         case 2:
8334                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8335                                                    r->out.count);
8336                 break;
8337         default:
8338                 return WERR_UNKNOWN_LEVEL;
8339         }
8340
8341         if (!W_ERROR_IS_OK(result)) {
8342                 return result;
8343         }
8344
8345         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8346                                                      spoolss_EnumMonitors, 
8347                                                      *r->out.info, r->in.level,
8348                                                      *r->out.count);
8349         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8350         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8351
8352         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8353 }
8354
8355 /****************************************************************************
8356 ****************************************************************************/
8357
8358 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8359                              const print_queue_struct *queue,
8360                              int count, int snum,
8361                              struct spoolss_PrinterInfo2 *pinfo2,
8362                              uint32_t jobid,
8363                              struct spoolss_JobInfo1 *r)
8364 {
8365         int i = 0;
8366         bool found = false;
8367
8368         for (i=0; i<count; i++) {
8369                 if (queue[i].job == (int)jobid) {
8370                         found = true;
8371                         break;
8372                 }
8373         }
8374
8375         if (found == false) {
8376                 /* NT treats not found as bad param... yet another bad choice */
8377                 return WERR_INVALID_PARAM;
8378         }
8379
8380         return fill_job_info1(mem_ctx,
8381                               r,
8382                               &queue[i],
8383                               i,
8384                               snum,
8385                               pinfo2);
8386 }
8387
8388 /****************************************************************************
8389 ****************************************************************************/
8390
8391 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8392                              const print_queue_struct *queue,
8393                              int count, int snum,
8394                              struct spoolss_PrinterInfo2 *pinfo2,
8395                              uint32_t jobid,
8396                              struct spoolss_JobInfo2 *r)
8397 {
8398         int i = 0;
8399         bool found = false;
8400         struct spoolss_DeviceMode *devmode;
8401         WERROR result;
8402
8403         for (i=0; i<count; i++) {
8404                 if (queue[i].job == (int)jobid) {
8405                         found = true;
8406                         break;
8407                 }
8408         }
8409
8410         if (found == false) {
8411                 /* NT treats not found as bad param... yet another bad
8412                    choice */
8413                 return WERR_INVALID_PARAM;
8414         }
8415
8416         /*
8417          * if the print job does not have a DEVMODE associated with it,
8418          * just use the one for the printer. A NULL devicemode is not
8419          *  a failure condition
8420          */
8421
8422         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8423         if (!devmode) {
8424                 result = spoolss_create_default_devmode(mem_ctx,
8425                                                 pinfo2->printername,
8426                                                 &devmode);
8427                 if (!W_ERROR_IS_OK(result)) {
8428                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8429                         return result;
8430                 }
8431         }
8432
8433         return fill_job_info2(mem_ctx,
8434                               r,
8435                               &queue[i],
8436                               i,
8437                               snum,
8438                               pinfo2,
8439                               devmode);
8440 }
8441
8442 /****************************************************************
8443  _spoolss_GetJob
8444 ****************************************************************/
8445
8446 WERROR _spoolss_GetJob(pipes_struct *p,
8447                        struct spoolss_GetJob *r)
8448 {
8449         WERROR result = WERR_OK;
8450         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8451         int snum;
8452         int count;
8453         print_queue_struct      *queue = NULL;
8454         print_status_struct prt_status;
8455
8456         /* that's an [in out] buffer */
8457
8458         if (!r->in.buffer && (r->in.offered != 0)) {
8459                 return WERR_INVALID_PARAM;
8460         }
8461
8462         DEBUG(5,("_spoolss_GetJob\n"));
8463
8464         *r->out.needed = 0;
8465
8466         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8467                 return WERR_BADFID;
8468         }
8469
8470         result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
8471                                     lp_servicename(snum), &pinfo2);
8472         if (!W_ERROR_IS_OK(result)) {
8473                 return result;
8474         }
8475
8476         count = print_queue_status(snum, &queue, &prt_status);
8477
8478         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8479                      count, prt_status.status, prt_status.message));
8480
8481         switch (r->in.level) {
8482         case 1:
8483                 result = getjob_level_1(p->mem_ctx,
8484                                         queue, count, snum, pinfo2,
8485                                         r->in.job_id, &r->out.info->info1);
8486                 break;
8487         case 2:
8488                 result = getjob_level_2(p->mem_ctx,
8489                                         queue, count, snum, pinfo2,
8490                                         r->in.job_id, &r->out.info->info2);
8491                 break;
8492         default:
8493                 result = WERR_UNKNOWN_LEVEL;
8494                 break;
8495         }
8496
8497         SAFE_FREE(queue);
8498         TALLOC_FREE(pinfo2);
8499
8500         if (!W_ERROR_IS_OK(result)) {
8501                 TALLOC_FREE(r->out.info);
8502                 return result;
8503         }
8504
8505         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8506                                                                                    r->in.level);
8507         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8508
8509         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8510 }
8511
8512 /****************************************************************
8513  _spoolss_GetPrinterDataEx
8514 ****************************************************************/
8515
8516 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8517                                  struct spoolss_GetPrinterDataEx *r)
8518 {
8519
8520         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8521         const char *printer;
8522         int                     snum = 0;
8523         WERROR result = WERR_OK;
8524         DATA_BLOB blob;
8525         enum winreg_Type val_type;
8526         uint8_t *val_data;
8527         uint32_t val_size;
8528
8529
8530         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8531
8532         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8533                 r->in.key_name, r->in.value_name));
8534
8535         /* in case of problem, return some default values */
8536
8537         *r->out.needed  = 0;
8538         *r->out.type    = REG_NONE;
8539
8540         if (!Printer) {
8541                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8542                         OUR_HANDLE(r->in.handle)));
8543                 result = WERR_BADFID;
8544                 goto done;
8545         }
8546
8547         /* Is the handle to a printer or to the server? */
8548
8549         if (Printer->printer_type == SPLHND_SERVER) {
8550
8551                 union spoolss_PrinterData data;
8552
8553                 result = getprinterdata_printer_server(p->mem_ctx,
8554                                                        r->in.value_name,
8555                                                        r->out.type,
8556                                                        &data);
8557                 if (!W_ERROR_IS_OK(result)) {
8558                         return result;
8559                 }
8560
8561                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8562                                                   *r->out.type, &data);
8563                 if (!W_ERROR_IS_OK(result)) {
8564                         return result;
8565                 }
8566
8567                 *r->out.needed = blob.length;
8568
8569                 if (r->in.offered >= *r->out.needed) {
8570                         memcpy(r->out.data, blob.data, blob.length);
8571                 }
8572
8573                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8574         }
8575
8576         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8577                 return WERR_BADFID;
8578         }
8579         printer = lp_const_servicename(snum);
8580
8581         /* check to see if the keyname is valid */
8582         if (!strlen(r->in.key_name)) {
8583                 return WERR_INVALID_PARAM;
8584         }
8585
8586         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8587         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8588             strequal(r->in.value_name, "ChangeId")) {
8589                 *r->out.type = REG_DWORD;
8590                 *r->out.needed = 4;
8591                 if (r->in.offered >= *r->out.needed) {
8592                         uint32_t changeid = 0;
8593
8594                         result = winreg_printer_get_changeid(p->mem_ctx,
8595                                                              p->server_info,
8596                                                              printer,
8597                                                              &changeid);
8598                         if (!W_ERROR_IS_OK(result)) {
8599                                 return result;
8600                         }
8601
8602                         SIVAL(r->out.data, 0, changeid);
8603                         result = WERR_OK;
8604                 }
8605                 goto done;
8606         }
8607
8608         result = winreg_get_printer_dataex(p->mem_ctx,
8609                                            p->server_info,
8610                                            printer,
8611                                            r->in.key_name,
8612                                            r->in.value_name,
8613                                            &val_type,
8614                                            &val_data,
8615                                            &val_size);
8616         if (!W_ERROR_IS_OK(result)) {
8617                 return result;
8618         }
8619
8620         *r->out.needed = val_size;
8621         *r->out.type = val_type;
8622
8623         if (r->in.offered >= *r->out.needed) {
8624                 memcpy(r->out.data, val_data, val_size);
8625         }
8626
8627  done:
8628         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8629         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8630
8631         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8632 }
8633
8634 /****************************************************************
8635  _spoolss_SetPrinterDataEx
8636 ****************************************************************/
8637
8638 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8639                                  struct spoolss_SetPrinterDataEx *r)
8640 {
8641         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8642         int                     snum = 0;
8643         WERROR                  result = WERR_OK;
8644         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8645         char                    *oid_string;
8646
8647         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8648
8649         /* From MSDN documentation of SetPrinterDataEx: pass request to
8650            SetPrinterData if key is "PrinterDriverData" */
8651
8652         if (!Printer) {
8653                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8654                         OUR_HANDLE(r->in.handle)));
8655                 return WERR_BADFID;
8656         }
8657
8658         if (Printer->printer_type == SPLHND_SERVER) {
8659                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8660                         "Not implemented for server handles yet\n"));
8661                 return WERR_INVALID_PARAM;
8662         }
8663
8664         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8665                 return WERR_BADFID;
8666         }
8667
8668         /*
8669          * Access check : NT returns "access denied" if you make a
8670          * SetPrinterData call without the necessary privildge.
8671          * we were originally returning OK if nothing changed
8672          * which made Win2k issue **a lot** of SetPrinterData
8673          * when connecting to a printer  --jerry
8674          */
8675
8676         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8677                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8678                         "change denied by handle access permissions\n"));
8679                 return WERR_ACCESS_DENIED;
8680         }
8681
8682         result = winreg_get_printer(Printer, p->server_info,
8683                                     Printer->servername,
8684                                     lp_servicename(snum),
8685                                     &pinfo2);
8686         if (!W_ERROR_IS_OK(result)) {
8687                 return result;
8688         }
8689
8690         /* check for OID in valuename */
8691
8692         oid_string = strchr(r->in.value_name, ',');
8693         if (oid_string) {
8694                 *oid_string = '\0';
8695                 oid_string++;
8696         }
8697
8698         /* save the registry data */
8699
8700         result = winreg_set_printer_dataex(p->mem_ctx,
8701                                            p->server_info,
8702                                            pinfo2->sharename,
8703                                            r->in.key_name,
8704                                            r->in.value_name,
8705                                            r->in.type,
8706                                            r->in.data,
8707                                            r->in.offered);
8708
8709         if (W_ERROR_IS_OK(result)) {
8710                 /* save the OID if one was specified */
8711                 if (oid_string) {
8712                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8713                                 r->in.key_name, SPOOL_OID_KEY);
8714                         if (!str) {
8715                                 result = WERR_NOMEM;
8716                                 goto done;
8717                         }
8718
8719                         /*
8720                          * I'm not checking the status here on purpose.  Don't know
8721                          * if this is right, but I'm returning the status from the
8722                          * previous set_printer_dataex() call.  I have no idea if
8723                          * this is right.    --jerry
8724                          */
8725                         winreg_set_printer_dataex(p->mem_ctx,
8726                                                   p->server_info,
8727                                                   pinfo2->sharename,
8728                                                   str,
8729                                                   r->in.value_name,
8730                                                   REG_SZ,
8731                                                   (uint8_t *) oid_string,
8732                                                   strlen(oid_string) + 1);
8733                 }
8734
8735                 result = winreg_printer_update_changeid(p->mem_ctx,
8736                                                         p->server_info,
8737                                                         lp_const_servicename(snum));
8738
8739         }
8740
8741 done:
8742         talloc_free(pinfo2);
8743         return result;
8744 }
8745
8746 /****************************************************************
8747  _spoolss_DeletePrinterDataEx
8748 ****************************************************************/
8749
8750 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8751                                     struct spoolss_DeletePrinterDataEx *r)
8752 {
8753         const char *printer;
8754         int             snum=0;
8755         WERROR          status = WERR_OK;
8756         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8757
8758         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8759
8760         if (!Printer) {
8761                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8762                         "Invalid handle (%s:%u:%u).\n",
8763                         OUR_HANDLE(r->in.handle)));
8764                 return WERR_BADFID;
8765         }
8766
8767         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8768                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8769                         "printer properties change denied by handle\n"));
8770                 return WERR_ACCESS_DENIED;
8771         }
8772
8773         if (!r->in.value_name || !r->in.key_name) {
8774                 return WERR_NOMEM;
8775         }
8776
8777         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8778                 return WERR_BADFID;
8779         }
8780         printer = lp_const_servicename(snum);
8781
8782         status = winreg_delete_printer_dataex(p->mem_ctx,
8783                                               p->server_info,
8784                                               printer,
8785                                               r->in.key_name,
8786                                               r->in.value_name);
8787         if (W_ERROR_IS_OK(status)) {
8788                 status = winreg_printer_update_changeid(p->mem_ctx,
8789                                                         p->server_info,
8790                                                         printer);
8791         }
8792
8793         return status;
8794 }
8795
8796 /****************************************************************
8797  _spoolss_EnumPrinterKey
8798 ****************************************************************/
8799
8800 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8801                                struct spoolss_EnumPrinterKey *r)
8802 {
8803         uint32_t        num_keys;
8804         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8805         int             snum = 0;
8806         WERROR          result = WERR_BADFILE;
8807         const char **array = NULL;
8808         DATA_BLOB blob;
8809
8810         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8811
8812         if (!Printer) {
8813                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8814                         OUR_HANDLE(r->in.handle)));
8815                 return WERR_BADFID;
8816         }
8817
8818         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8819                 return WERR_BADFID;
8820         }
8821
8822         result = winreg_enum_printer_key(p->mem_ctx,
8823                                          p->server_info,
8824                                          lp_const_servicename(snum),
8825                                          r->in.key_name,
8826                                          &num_keys,
8827                                          &array);
8828         if (!W_ERROR_IS_OK(result)) {
8829                 goto done;
8830         }
8831
8832         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8833                 result = WERR_NOMEM;
8834                 goto done;
8835         }
8836
8837         *r->out._ndr_size = r->in.offered / 2;
8838         *r->out.needed = blob.length;
8839
8840         if (r->in.offered < *r->out.needed) {
8841                 result = WERR_MORE_DATA;
8842         } else {
8843                 result = WERR_OK;
8844                 r->out.key_buffer->string_array = array;
8845         }
8846
8847  done:
8848         if (!W_ERROR_IS_OK(result)) {
8849                 TALLOC_FREE(array);
8850                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8851                         *r->out.needed = 0;
8852                 }
8853         }
8854
8855         return result;
8856 }
8857
8858 /****************************************************************
8859  _spoolss_DeletePrinterKey
8860 ****************************************************************/
8861
8862 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8863                                  struct spoolss_DeletePrinterKey *r)
8864 {
8865         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8866         int                     snum=0;
8867         WERROR                  status;
8868         const char *printer;
8869
8870         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8871
8872         if (!Printer) {
8873                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8874                         OUR_HANDLE(r->in.handle)));
8875                 return WERR_BADFID;
8876         }
8877
8878         /* if keyname == NULL, return error */
8879         if ( !r->in.key_name )
8880                 return WERR_INVALID_PARAM;
8881
8882         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8883                 return WERR_BADFID;
8884         }
8885
8886         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8887                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8888                         "printer properties change denied by handle\n"));
8889                 return WERR_ACCESS_DENIED;
8890         }
8891
8892         printer = lp_const_servicename(snum);
8893
8894         /* delete the key and all subkeys */
8895         status = winreg_delete_printer_key(p->mem_ctx,
8896                                            p->server_info,
8897                                            printer,
8898                                            r->in.key_name);
8899         if (W_ERROR_IS_OK(status)) {
8900                 status = winreg_printer_update_changeid(p->mem_ctx,
8901                                                         p->server_info,
8902                                                         printer);
8903         }
8904
8905         return status;
8906 }
8907
8908 /****************************************************************
8909  _spoolss_EnumPrinterDataEx
8910 ****************************************************************/
8911
8912 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8913                                   struct spoolss_EnumPrinterDataEx *r)
8914 {
8915         uint32_t        count = 0;
8916         struct spoolss_PrinterEnumValues *info = NULL;
8917         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8918         int             snum;
8919         WERROR          result;
8920
8921         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8922
8923         *r->out.count = 0;
8924         *r->out.needed = 0;
8925         *r->out.info = NULL;
8926
8927         if (!Printer) {
8928                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8929                         OUR_HANDLE(r->in.handle)));
8930                 return WERR_BADFID;
8931         }
8932
8933         /*
8934          * first check for a keyname of NULL or "".  Win2k seems to send
8935          * this a lot and we should send back WERR_INVALID_PARAM
8936          * no need to spend time looking up the printer in this case.
8937          * --jerry
8938          */
8939
8940         if (!strlen(r->in.key_name)) {
8941                 result = WERR_INVALID_PARAM;
8942                 goto done;
8943         }
8944
8945         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8946                 return WERR_BADFID;
8947         }
8948
8949         /* now look for a match on the key name */
8950         result = winreg_enum_printer_dataex(p->mem_ctx,
8951                                             p->server_info,
8952                                             lp_const_servicename(snum),
8953                                             r->in.key_name,
8954                                             &count,
8955                                             &info);
8956         if (!W_ERROR_IS_OK(result)) {
8957                 goto done;
8958         }
8959
8960 #if 0 /* FIXME - gd */
8961         /* housekeeping information in the reply */
8962
8963         /* Fix from Martin Zielinski <mz@seh.de> - ensure
8964          * the hand marshalled container size is a multiple
8965          * of 4 bytes for RPC alignment.
8966          */
8967
8968         if (needed % 4) {
8969                 needed += 4-(needed % 4);
8970         }
8971 #endif
8972         *r->out.count   = count;
8973         *r->out.info    = info;
8974
8975  done:
8976         if (!W_ERROR_IS_OK(result)) {
8977                 return result;
8978         }
8979
8980         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8981                                                spoolss_EnumPrinterDataEx, 
8982                                                *r->out.info,
8983                                                *r->out.count);
8984         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8985         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8986
8987         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8988 }
8989
8990 /****************************************************************************
8991 ****************************************************************************/
8992
8993 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8994                                                  const char *servername,
8995                                                  const char *environment,
8996                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
8997 {
8998         WERROR werr;
8999         char *path = NULL;
9000
9001         werr = compose_spoolss_server_path(mem_ctx,
9002                                            servername,
9003                                            environment,
9004                                            SPOOLSS_PRTPROCS_PATH,
9005                                            &path);
9006         if (!W_ERROR_IS_OK(werr)) {
9007                 return werr;
9008         }
9009
9010         DEBUG(4,("print processor directory: [%s]\n", path));
9011
9012         r->directory_name = path;
9013
9014         return WERR_OK;
9015 }
9016
9017 /****************************************************************
9018  _spoolss_GetPrintProcessorDirectory
9019 ****************************************************************/
9020
9021 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9022                                            struct spoolss_GetPrintProcessorDirectory *r)
9023 {
9024         WERROR result;
9025
9026         /* that's an [in out] buffer */
9027
9028         if (!r->in.buffer && (r->in.offered != 0)) {
9029                 return WERR_INVALID_PARAM;
9030         }
9031
9032         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9033                 r->in.level));
9034
9035         *r->out.needed = 0;
9036
9037         /* r->in.level is ignored */
9038
9039         /* We always should reply with a local print processor directory so that
9040          * users are not forced to have a [prnproc$] share on the Samba spoolss
9041          * server - Guenther */
9042
9043         result = getprintprocessordirectory_level_1(p->mem_ctx,
9044                                                     NULL, /* r->in.server */
9045                                                     r->in.environment,
9046                                                     &r->out.info->info1);
9047         if (!W_ERROR_IS_OK(result)) {
9048                 TALLOC_FREE(r->out.info);
9049                 return result;
9050         }
9051
9052         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9053                                                                                    r->out.info, r->in.level);
9054         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9055
9056         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9057 }
9058
9059 /*******************************************************************
9060  ********************************************************************/
9061
9062 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9063                                const char *dllname)
9064 {
9065         enum ndr_err_code ndr_err;
9066         struct spoolss_MonitorUi ui;
9067
9068         ui.dll_name = dllname;
9069
9070         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9071                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9072         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9073                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9074         }
9075         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9076 }
9077
9078 /*******************************************************************
9079  Streams the monitor UI DLL name in UNICODE
9080 *******************************************************************/
9081
9082 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9083                                NT_USER_TOKEN *token, DATA_BLOB *in,
9084                                DATA_BLOB *out, uint32_t *needed)
9085 {
9086         const char *dllname = "tcpmonui.dll";
9087
9088         *needed = (strlen(dllname)+1) * 2;
9089
9090         if (out->length < *needed) {
9091                 return WERR_INSUFFICIENT_BUFFER;
9092         }
9093
9094         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9095                 return WERR_NOMEM;
9096         }
9097
9098         return WERR_OK;
9099 }
9100
9101 /*******************************************************************
9102  ********************************************************************/
9103
9104 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9105                              struct spoolss_PortData1 *port1,
9106                              const DATA_BLOB *buf)
9107 {
9108         enum ndr_err_code ndr_err;
9109         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9110                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9111         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9112                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9113         }
9114         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9115 }
9116
9117 /*******************************************************************
9118  ********************************************************************/
9119
9120 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9121                              struct spoolss_PortData2 *port2,
9122                              const DATA_BLOB *buf)
9123 {
9124         enum ndr_err_code ndr_err;
9125         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9126                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9127         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9128                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9129         }
9130         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9131 }
9132
9133 /*******************************************************************
9134  Create a new TCP/IP port
9135 *******************************************************************/
9136
9137 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9138                              NT_USER_TOKEN *token, DATA_BLOB *in,
9139                              DATA_BLOB *out, uint32_t *needed)
9140 {
9141         struct spoolss_PortData1 port1;
9142         struct spoolss_PortData2 port2;
9143         char *device_uri = NULL;
9144         uint32_t version;
9145
9146         const char *portname;
9147         const char *hostaddress;
9148         const char *queue;
9149         uint32_t port_number;
9150         uint32_t protocol;
9151
9152         /* peek for spoolss_PortData version */
9153
9154         if (!in || (in->length < (128 + 4))) {
9155                 return WERR_GENERAL_FAILURE;
9156         }
9157
9158         version = IVAL(in->data, 128);
9159
9160         switch (version) {
9161                 case 1:
9162                         ZERO_STRUCT(port1);
9163
9164                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9165                                 return WERR_NOMEM;
9166                         }
9167
9168                         portname        = port1.portname;
9169                         hostaddress     = port1.hostaddress;
9170                         queue           = port1.queue;
9171                         protocol        = port1.protocol;
9172                         port_number     = port1.port_number;
9173
9174                         break;
9175                 case 2:
9176                         ZERO_STRUCT(port2);
9177
9178                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9179                                 return WERR_NOMEM;
9180                         }
9181
9182                         portname        = port2.portname;
9183                         hostaddress     = port2.hostaddress;
9184                         queue           = port2.queue;
9185                         protocol        = port2.protocol;
9186                         port_number     = port2.port_number;
9187
9188                         break;
9189                 default:
9190                         DEBUG(1,("xcvtcp_addport: "
9191                                 "unknown version of port_data: %d\n", version));
9192                         return WERR_UNKNOWN_PORT;
9193         }
9194
9195         /* create the device URI and call the add_port_hook() */
9196
9197         switch (protocol) {
9198         case PROTOCOL_RAWTCP_TYPE:
9199                 device_uri = talloc_asprintf(mem_ctx,
9200                                 "socket://%s:%d/", hostaddress,
9201                                 port_number);
9202                 break;
9203
9204         case PROTOCOL_LPR_TYPE:
9205                 device_uri = talloc_asprintf(mem_ctx,
9206                         "lpr://%s/%s", hostaddress, queue );
9207                 break;
9208
9209         default:
9210                 return WERR_UNKNOWN_PORT;
9211         }
9212
9213         if (!device_uri) {
9214                 return WERR_NOMEM;
9215         }
9216
9217         return add_port_hook(mem_ctx, token, portname, device_uri);
9218 }
9219
9220 /*******************************************************************
9221 *******************************************************************/
9222
9223 struct xcv_api_table xcvtcp_cmds[] = {
9224         { "MonitorUI",  xcvtcp_monitorui },
9225         { "AddPort",    xcvtcp_addport},
9226         { NULL,         NULL }
9227 };
9228
9229 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9230                                      NT_USER_TOKEN *token, const char *command,
9231                                      DATA_BLOB *inbuf,
9232                                      DATA_BLOB *outbuf,
9233                                      uint32_t *needed )
9234 {
9235         int i;
9236
9237         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9238
9239         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9240                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9241                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9242         }
9243
9244         return WERR_BADFUNC;
9245 }
9246
9247 /*******************************************************************
9248 *******************************************************************/
9249 #if 0   /* don't support management using the "Local Port" monitor */
9250
9251 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9252                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9253                                  DATA_BLOB *out, uint32_t *needed)
9254 {
9255         const char *dllname = "localui.dll";
9256
9257         *needed = (strlen(dllname)+1) * 2;
9258
9259         if (out->length < *needed) {
9260                 return WERR_INSUFFICIENT_BUFFER;
9261         }
9262
9263         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9264                 return WERR_NOMEM;
9265         }
9266
9267         return WERR_OK;
9268 }
9269
9270 /*******************************************************************
9271 *******************************************************************/
9272
9273 struct xcv_api_table xcvlocal_cmds[] = {
9274         { "MonitorUI",  xcvlocal_monitorui },
9275         { NULL,         NULL }
9276 };
9277 #else
9278 struct xcv_api_table xcvlocal_cmds[] = {
9279         { NULL,         NULL }
9280 };
9281 #endif
9282
9283
9284
9285 /*******************************************************************
9286 *******************************************************************/
9287
9288 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9289                                        NT_USER_TOKEN *token, const char *command,
9290                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9291                                        uint32_t *needed)
9292 {
9293         int i;
9294
9295         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9296
9297         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9298                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9299                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9300         }
9301         return WERR_BADFUNC;
9302 }
9303
9304 /****************************************************************
9305  _spoolss_XcvData
9306 ****************************************************************/
9307
9308 WERROR _spoolss_XcvData(pipes_struct *p,
9309                         struct spoolss_XcvData *r)
9310 {
9311         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9312         DATA_BLOB out_data = data_blob_null;
9313         WERROR werror;
9314
9315         if (!Printer) {
9316                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9317                         OUR_HANDLE(r->in.handle)));
9318                 return WERR_BADFID;
9319         }
9320
9321         /* Has to be a handle to the TCP/IP port monitor */
9322
9323         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9324                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9325                 return WERR_BADFID;
9326         }
9327
9328         /* requires administrative access to the server */
9329
9330         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9331                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9332                 return WERR_ACCESS_DENIED;
9333         }
9334
9335         /* Allocate the outgoing buffer */
9336
9337         if (r->in.out_data_size) {
9338                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9339                 if (out_data.data == NULL) {
9340                         return WERR_NOMEM;
9341                 }
9342         }
9343
9344         switch ( Printer->printer_type ) {
9345         case SPLHND_PORTMON_TCP:
9346                 werror = process_xcvtcp_command(p->mem_ctx,
9347                                                 p->server_info->ptok,
9348                                                 r->in.function_name,
9349                                                 &r->in.in_data, &out_data,
9350                                                 r->out.needed);
9351                 break;
9352         case SPLHND_PORTMON_LOCAL:
9353                 werror = process_xcvlocal_command(p->mem_ctx,
9354                                                   p->server_info->ptok,
9355                                                   r->in.function_name,
9356                                                   &r->in.in_data, &out_data,
9357                                                   r->out.needed);
9358                 break;
9359         default:
9360                 werror = WERR_INVALID_PRINT_MONITOR;
9361         }
9362
9363         if (!W_ERROR_IS_OK(werror)) {
9364                 return werror;
9365         }
9366
9367         *r->out.status_code = 0;
9368
9369         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9370                 memcpy(r->out.out_data, out_data.data,
9371                         MIN(r->in.out_data_size, out_data.length));
9372         }
9373
9374         return WERR_OK;
9375 }
9376
9377 /****************************************************************
9378  _spoolss_AddPrintProcessor
9379 ****************************************************************/
9380
9381 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9382                                   struct spoolss_AddPrintProcessor *r)
9383 {
9384         /* for now, just indicate success and ignore the add.  We'll
9385            automatically set the winprint processor for printer
9386            entries later.  Used to debug the LexMark Optra S 1855 PCL
9387            driver --jerry */
9388
9389         return WERR_OK;
9390 }
9391
9392 /****************************************************************
9393  _spoolss_AddPort
9394 ****************************************************************/
9395
9396 WERROR _spoolss_AddPort(pipes_struct *p,
9397                         struct spoolss_AddPort *r)
9398 {
9399         /* do what w2k3 does */
9400
9401         return WERR_NOT_SUPPORTED;
9402 }
9403
9404 /****************************************************************
9405  _spoolss_GetPrinterDriver
9406 ****************************************************************/
9407
9408 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9409                                  struct spoolss_GetPrinterDriver *r)
9410 {
9411         p->rng_fault_state = true;
9412         return WERR_NOT_SUPPORTED;
9413 }
9414
9415 /****************************************************************
9416  _spoolss_ReadPrinter
9417 ****************************************************************/
9418
9419 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9420                             struct spoolss_ReadPrinter *r)
9421 {
9422         p->rng_fault_state = true;
9423         return WERR_NOT_SUPPORTED;
9424 }
9425
9426 /****************************************************************
9427  _spoolss_WaitForPrinterChange
9428 ****************************************************************/
9429
9430 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9431                                      struct spoolss_WaitForPrinterChange *r)
9432 {
9433         p->rng_fault_state = true;
9434         return WERR_NOT_SUPPORTED;
9435 }
9436
9437 /****************************************************************
9438  _spoolss_ConfigurePort
9439 ****************************************************************/
9440
9441 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9442                               struct spoolss_ConfigurePort *r)
9443 {
9444         p->rng_fault_state = true;
9445         return WERR_NOT_SUPPORTED;
9446 }
9447
9448 /****************************************************************
9449  _spoolss_DeletePort
9450 ****************************************************************/
9451
9452 WERROR _spoolss_DeletePort(pipes_struct *p,
9453                            struct spoolss_DeletePort *r)
9454 {
9455         p->rng_fault_state = true;
9456         return WERR_NOT_SUPPORTED;
9457 }
9458
9459 /****************************************************************
9460  _spoolss_CreatePrinterIC
9461 ****************************************************************/
9462
9463 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9464                                 struct spoolss_CreatePrinterIC *r)
9465 {
9466         p->rng_fault_state = true;
9467         return WERR_NOT_SUPPORTED;
9468 }
9469
9470 /****************************************************************
9471  _spoolss_PlayGDIScriptOnPrinterIC
9472 ****************************************************************/
9473
9474 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9475                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9476 {
9477         p->rng_fault_state = true;
9478         return WERR_NOT_SUPPORTED;
9479 }
9480
9481 /****************************************************************
9482  _spoolss_DeletePrinterIC
9483 ****************************************************************/
9484
9485 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9486                                 struct spoolss_DeletePrinterIC *r)
9487 {
9488         p->rng_fault_state = true;
9489         return WERR_NOT_SUPPORTED;
9490 }
9491
9492 /****************************************************************
9493  _spoolss_AddPrinterConnection
9494 ****************************************************************/
9495
9496 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9497                                      struct spoolss_AddPrinterConnection *r)
9498 {
9499         p->rng_fault_state = true;
9500         return WERR_NOT_SUPPORTED;
9501 }
9502
9503 /****************************************************************
9504  _spoolss_DeletePrinterConnection
9505 ****************************************************************/
9506
9507 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9508                                         struct spoolss_DeletePrinterConnection *r)
9509 {
9510         p->rng_fault_state = true;
9511         return WERR_NOT_SUPPORTED;
9512 }
9513
9514 /****************************************************************
9515  _spoolss_PrinterMessageBox
9516 ****************************************************************/
9517
9518 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9519                                   struct spoolss_PrinterMessageBox *r)
9520 {
9521         p->rng_fault_state = true;
9522         return WERR_NOT_SUPPORTED;
9523 }
9524
9525 /****************************************************************
9526  _spoolss_AddMonitor
9527 ****************************************************************/
9528
9529 WERROR _spoolss_AddMonitor(pipes_struct *p,
9530                            struct spoolss_AddMonitor *r)
9531 {
9532         p->rng_fault_state = true;
9533         return WERR_NOT_SUPPORTED;
9534 }
9535
9536 /****************************************************************
9537  _spoolss_DeleteMonitor
9538 ****************************************************************/
9539
9540 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9541                               struct spoolss_DeleteMonitor *r)
9542 {
9543         p->rng_fault_state = true;
9544         return WERR_NOT_SUPPORTED;
9545 }
9546
9547 /****************************************************************
9548  _spoolss_DeletePrintProcessor
9549 ****************************************************************/
9550
9551 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9552                                      struct spoolss_DeletePrintProcessor *r)
9553 {
9554         p->rng_fault_state = true;
9555         return WERR_NOT_SUPPORTED;
9556 }
9557
9558 /****************************************************************
9559  _spoolss_AddPrintProvidor
9560 ****************************************************************/
9561
9562 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9563                                  struct spoolss_AddPrintProvidor *r)
9564 {
9565         p->rng_fault_state = true;
9566         return WERR_NOT_SUPPORTED;
9567 }
9568
9569 /****************************************************************
9570  _spoolss_DeletePrintProvidor
9571 ****************************************************************/
9572
9573 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9574                                     struct spoolss_DeletePrintProvidor *r)
9575 {
9576         p->rng_fault_state = true;
9577         return WERR_NOT_SUPPORTED;
9578 }
9579
9580 /****************************************************************
9581  _spoolss_FindFirstPrinterChangeNotification
9582 ****************************************************************/
9583
9584 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9585                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9586 {
9587         p->rng_fault_state = true;
9588         return WERR_NOT_SUPPORTED;
9589 }
9590
9591 /****************************************************************
9592  _spoolss_FindNextPrinterChangeNotification
9593 ****************************************************************/
9594
9595 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9596                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9597 {
9598         p->rng_fault_state = true;
9599         return WERR_NOT_SUPPORTED;
9600 }
9601
9602 /****************************************************************
9603  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9604 ****************************************************************/
9605
9606 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9607                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9608 {
9609         p->rng_fault_state = true;
9610         return WERR_NOT_SUPPORTED;
9611 }
9612
9613 /****************************************************************
9614  _spoolss_ReplyOpenPrinter
9615 ****************************************************************/
9616
9617 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9618                                  struct spoolss_ReplyOpenPrinter *r)
9619 {
9620         p->rng_fault_state = true;
9621         return WERR_NOT_SUPPORTED;
9622 }
9623
9624 /****************************************************************
9625  _spoolss_RouterReplyPrinter
9626 ****************************************************************/
9627
9628 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9629                                    struct spoolss_RouterReplyPrinter *r)
9630 {
9631         p->rng_fault_state = true;
9632         return WERR_NOT_SUPPORTED;
9633 }
9634
9635 /****************************************************************
9636  _spoolss_ReplyClosePrinter
9637 ****************************************************************/
9638
9639 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9640                                   struct spoolss_ReplyClosePrinter *r)
9641 {
9642         p->rng_fault_state = true;
9643         return WERR_NOT_SUPPORTED;
9644 }
9645
9646 /****************************************************************
9647  _spoolss_AddPortEx
9648 ****************************************************************/
9649
9650 WERROR _spoolss_AddPortEx(pipes_struct *p,
9651                           struct spoolss_AddPortEx *r)
9652 {
9653         p->rng_fault_state = true;
9654         return WERR_NOT_SUPPORTED;
9655 }
9656
9657 /****************************************************************
9658  _spoolss_RouterFindFirstPrinterChangeNotification
9659 ****************************************************************/
9660
9661 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9662                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9663 {
9664         p->rng_fault_state = true;
9665         return WERR_NOT_SUPPORTED;
9666 }
9667
9668 /****************************************************************
9669  _spoolss_SpoolerInit
9670 ****************************************************************/
9671
9672 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9673                             struct spoolss_SpoolerInit *r)
9674 {
9675         p->rng_fault_state = true;
9676         return WERR_NOT_SUPPORTED;
9677 }
9678
9679 /****************************************************************
9680  _spoolss_ResetPrinterEx
9681 ****************************************************************/
9682
9683 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9684                                struct spoolss_ResetPrinterEx *r)
9685 {
9686         p->rng_fault_state = true;
9687         return WERR_NOT_SUPPORTED;
9688 }
9689
9690 /****************************************************************
9691  _spoolss_RouterReplyPrinterEx
9692 ****************************************************************/
9693
9694 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9695                                      struct spoolss_RouterReplyPrinterEx *r)
9696 {
9697         p->rng_fault_state = true;
9698         return WERR_NOT_SUPPORTED;
9699 }
9700
9701 /****************************************************************
9702  _spoolss_44
9703 ****************************************************************/
9704
9705 WERROR _spoolss_44(pipes_struct *p,
9706                    struct spoolss_44 *r)
9707 {
9708         p->rng_fault_state = true;
9709         return WERR_NOT_SUPPORTED;
9710 }
9711
9712 /****************************************************************
9713  _spoolss_47
9714 ****************************************************************/
9715
9716 WERROR _spoolss_47(pipes_struct *p,
9717                    struct spoolss_47 *r)
9718 {
9719         p->rng_fault_state = true;
9720         return WERR_NOT_SUPPORTED;
9721 }
9722
9723 /****************************************************************
9724  _spoolss_4a
9725 ****************************************************************/
9726
9727 WERROR _spoolss_4a(pipes_struct *p,
9728                    struct spoolss_4a *r)
9729 {
9730         p->rng_fault_state = true;
9731         return WERR_NOT_SUPPORTED;
9732 }
9733
9734 /****************************************************************
9735  _spoolss_4b
9736 ****************************************************************/
9737
9738 WERROR _spoolss_4b(pipes_struct *p,
9739                    struct spoolss_4b *r)
9740 {
9741         p->rng_fault_state = true;
9742         return WERR_NOT_SUPPORTED;
9743 }
9744
9745 /****************************************************************
9746  _spoolss_4c
9747 ****************************************************************/
9748
9749 WERROR _spoolss_4c(pipes_struct *p,
9750                    struct spoolss_4c *r)
9751 {
9752         p->rng_fault_state = true;
9753         return WERR_NOT_SUPPORTED;
9754 }
9755
9756 /****************************************************************
9757  _spoolss_53
9758 ****************************************************************/
9759
9760 WERROR _spoolss_53(pipes_struct *p,
9761                    struct spoolss_53 *r)
9762 {
9763         p->rng_fault_state = true;
9764         return WERR_NOT_SUPPORTED;
9765 }
9766
9767 /****************************************************************
9768  _spoolss_55
9769 ****************************************************************/
9770
9771 WERROR _spoolss_55(pipes_struct *p,
9772                    struct spoolss_55 *r)
9773 {
9774         p->rng_fault_state = true;
9775         return WERR_NOT_SUPPORTED;
9776 }
9777
9778 /****************************************************************
9779  _spoolss_56
9780 ****************************************************************/
9781
9782 WERROR _spoolss_56(pipes_struct *p,
9783                    struct spoolss_56 *r)
9784 {
9785         p->rng_fault_state = true;
9786         return WERR_NOT_SUPPORTED;
9787 }
9788
9789 /****************************************************************
9790  _spoolss_57
9791 ****************************************************************/
9792
9793 WERROR _spoolss_57(pipes_struct *p,
9794                    struct spoolss_57 *r)
9795 {
9796         p->rng_fault_state = true;
9797         return WERR_NOT_SUPPORTED;
9798 }
9799
9800 /****************************************************************
9801  _spoolss_5a
9802 ****************************************************************/
9803
9804 WERROR _spoolss_5a(pipes_struct *p,
9805                    struct spoolss_5a *r)
9806 {
9807         p->rng_fault_state = true;
9808         return WERR_NOT_SUPPORTED;
9809 }
9810
9811 /****************************************************************
9812  _spoolss_5b
9813 ****************************************************************/
9814
9815 WERROR _spoolss_5b(pipes_struct *p,
9816                    struct spoolss_5b *r)
9817 {
9818         p->rng_fault_state = true;
9819         return WERR_NOT_SUPPORTED;
9820 }
9821
9822 /****************************************************************
9823  _spoolss_5c
9824 ****************************************************************/
9825
9826 WERROR _spoolss_5c(pipes_struct *p,
9827                    struct spoolss_5c *r)
9828 {
9829         p->rng_fault_state = true;
9830         return WERR_NOT_SUPPORTED;
9831 }
9832
9833 /****************************************************************
9834  _spoolss_5d
9835 ****************************************************************/
9836
9837 WERROR _spoolss_5d(pipes_struct *p,
9838                    struct spoolss_5d *r)
9839 {
9840         p->rng_fault_state = true;
9841         return WERR_NOT_SUPPORTED;
9842 }
9843
9844 /****************************************************************
9845  _spoolss_5e
9846 ****************************************************************/
9847
9848 WERROR _spoolss_5e(pipes_struct *p,
9849                    struct spoolss_5e *r)
9850 {
9851         p->rng_fault_state = true;
9852         return WERR_NOT_SUPPORTED;
9853 }
9854
9855 /****************************************************************
9856  _spoolss_5f
9857 ****************************************************************/
9858
9859 WERROR _spoolss_5f(pipes_struct *p,
9860                    struct spoolss_5f *r)
9861 {
9862         p->rng_fault_state = true;
9863         return WERR_NOT_SUPPORTED;
9864 }
9865
9866 /****************************************************************
9867  _spoolss_60
9868 ****************************************************************/
9869
9870 WERROR _spoolss_60(pipes_struct *p,
9871                    struct spoolss_60 *r)
9872 {
9873         p->rng_fault_state = true;
9874         return WERR_NOT_SUPPORTED;
9875 }
9876
9877 /****************************************************************
9878  _spoolss_61
9879 ****************************************************************/
9880
9881 WERROR _spoolss_61(pipes_struct *p,
9882                    struct spoolss_61 *r)
9883 {
9884         p->rng_fault_state = true;
9885         return WERR_NOT_SUPPORTED;
9886 }
9887
9888 /****************************************************************
9889  _spoolss_62
9890 ****************************************************************/
9891
9892 WERROR _spoolss_62(pipes_struct *p,
9893                    struct spoolss_62 *r)
9894 {
9895         p->rng_fault_state = true;
9896         return WERR_NOT_SUPPORTED;
9897 }
9898
9899 /****************************************************************
9900  _spoolss_63
9901 ****************************************************************/
9902
9903 WERROR _spoolss_63(pipes_struct *p,
9904                    struct spoolss_63 *r)
9905 {
9906         p->rng_fault_state = true;
9907         return WERR_NOT_SUPPORTED;
9908 }
9909
9910 /****************************************************************
9911  _spoolss_64
9912 ****************************************************************/
9913
9914 WERROR _spoolss_64(pipes_struct *p,
9915                    struct spoolss_64 *r)
9916 {
9917         p->rng_fault_state = true;
9918         return WERR_NOT_SUPPORTED;
9919 }
9920
9921 /****************************************************************
9922  _spoolss_65
9923 ****************************************************************/
9924
9925 WERROR _spoolss_65(pipes_struct *p,
9926                    struct spoolss_65 *r)
9927 {
9928         p->rng_fault_state = true;
9929         return WERR_NOT_SUPPORTED;
9930 }
9931
9932 /****************************************************************
9933  _spoolss_GetCorePrinterDrivers
9934 ****************************************************************/
9935
9936 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9937                                       struct spoolss_GetCorePrinterDrivers *r)
9938 {
9939         p->rng_fault_state = true;
9940         return WERR_NOT_SUPPORTED;
9941 }
9942
9943 /****************************************************************
9944  _spoolss_67
9945 ****************************************************************/
9946
9947 WERROR _spoolss_67(pipes_struct *p,
9948                    struct spoolss_67 *r)
9949 {
9950         p->rng_fault_state = true;
9951         return WERR_NOT_SUPPORTED;
9952 }
9953
9954 /****************************************************************
9955  _spoolss_GetPrinterDriverPackagePath
9956 ****************************************************************/
9957
9958 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9959                                             struct spoolss_GetPrinterDriverPackagePath *r)
9960 {
9961         p->rng_fault_state = true;
9962         return WERR_NOT_SUPPORTED;
9963 }
9964
9965 /****************************************************************
9966  _spoolss_69
9967 ****************************************************************/
9968
9969 WERROR _spoolss_69(pipes_struct *p,
9970                    struct spoolss_69 *r)
9971 {
9972         p->rng_fault_state = true;
9973         return WERR_NOT_SUPPORTED;
9974 }
9975
9976 /****************************************************************
9977  _spoolss_6a
9978 ****************************************************************/
9979
9980 WERROR _spoolss_6a(pipes_struct *p,
9981                    struct spoolss_6a *r)
9982 {
9983         p->rng_fault_state = true;
9984         return WERR_NOT_SUPPORTED;
9985 }
9986
9987 /****************************************************************
9988  _spoolss_6b
9989 ****************************************************************/
9990
9991 WERROR _spoolss_6b(pipes_struct *p,
9992                    struct spoolss_6b *r)
9993 {
9994         p->rng_fault_state = true;
9995         return WERR_NOT_SUPPORTED;
9996 }
9997
9998 /****************************************************************
9999  _spoolss_6c
10000 ****************************************************************/
10001
10002 WERROR _spoolss_6c(pipes_struct *p,
10003                    struct spoolss_6c *r)
10004 {
10005         p->rng_fault_state = true;
10006         return WERR_NOT_SUPPORTED;
10007 }
10008
10009 /****************************************************************
10010  _spoolss_6d
10011 ****************************************************************/
10012
10013 WERROR _spoolss_6d(pipes_struct *p,
10014                    struct spoolss_6d *r)
10015 {
10016         p->rng_fault_state = true;
10017         return WERR_NOT_SUPPORTED;
10018 }