s3-spoolss: Use a temporary talloc context in update_printer.
[abartlet/samba.git/.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 "srv_spoolss_util.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "librpc/gen_ndr/messaging.h"
36 #include "librpc/gen_ndr/ndr_security.h"
37 #include "registry.h"
38 #include "registry/reg_objects.h"
39
40 /* macros stolen from s4 spoolss server */
41 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
42         ((info)?ndr_size_##fn(info, level, 0):0)
43
44 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
45         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
46
47 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
48         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
49
50 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
51
52
53 extern userdom_struct current_user_info;
54
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_RPC_SRV
57
58 #ifndef MAX_OPEN_PRINTER_EXS
59 #define MAX_OPEN_PRINTER_EXS 50
60 #endif
61
62 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
63
64 static Printer_entry *printers_list;
65
66 typedef struct _counter_printer_0 {
67         struct _counter_printer_0 *next;
68         struct _counter_printer_0 *prev;
69
70         int snum;
71         uint32_t counter;
72 } counter_printer_0;
73
74 static counter_printer_0 *counter_list;
75
76 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
77 static uint32_t smb_connections = 0;
78
79
80 /* in printing/nt_printing.c */
81
82 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
83
84 /* API table for Xcv Monitor functions */
85
86 struct xcv_api_table {
87         const char *name;
88         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
89 };
90
91 /********************************************************************
92  * Canonicalize servername.
93  ********************************************************************/
94
95 static const char *canon_servername(const char *servername)
96 {
97         const char *pservername = servername;
98         while (*pservername == '\\') {
99                 pservername++;
100         }
101         return pservername;
102 }
103
104 /* translate between internal status numbers and NT status numbers */
105 static int nt_printj_status(int v)
106 {
107         switch (v) {
108         case LPQ_QUEUED:
109                 return 0;
110         case LPQ_PAUSED:
111                 return JOB_STATUS_PAUSED;
112         case LPQ_SPOOLING:
113                 return JOB_STATUS_SPOOLING;
114         case LPQ_PRINTING:
115                 return JOB_STATUS_PRINTING;
116         case LPQ_ERROR:
117                 return JOB_STATUS_ERROR;
118         case LPQ_DELETING:
119                 return JOB_STATUS_DELETING;
120         case LPQ_OFFLINE:
121                 return JOB_STATUS_OFFLINE;
122         case LPQ_PAPEROUT:
123                 return JOB_STATUS_PAPEROUT;
124         case LPQ_PRINTED:
125                 return JOB_STATUS_PRINTED;
126         case LPQ_DELETED:
127                 return JOB_STATUS_DELETED;
128         case LPQ_BLOCKED:
129                 return JOB_STATUS_BLOCKED_DEVQ;
130         case LPQ_USER_INTERVENTION:
131                 return JOB_STATUS_USER_INTERVENTION;
132         }
133         return 0;
134 }
135
136 static int nt_printq_status(int v)
137 {
138         switch (v) {
139         case LPQ_PAUSED:
140                 return PRINTER_STATUS_PAUSED;
141         case LPQ_QUEUED:
142         case LPQ_SPOOLING:
143         case LPQ_PRINTING:
144                 return 0;
145         }
146         return 0;
147 }
148
149 /***************************************************************************
150  Disconnect from the client
151 ****************************************************************************/
152
153 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
154 {
155         WERROR result;
156         NTSTATUS status;
157
158         /*
159          * Tell the specific printing tdb we no longer want messages for this printer
160          * by deregistering our PID.
161          */
162
163         if (!print_notify_deregister_pid(snum))
164                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
165
166         /* weird if the test succeds !!! */
167         if (smb_connections==0) {
168                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169                 return;
170         }
171
172         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
173                                                   handle,
174                                                   &result);
175         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
176                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177                         win_errstr(result)));
178
179         /* if it's the last connection, deconnect the IPC$ share */
180         if (smb_connections==1) {
181
182                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
183                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
184
185                 messaging_deregister(smbd_messaging_context(),
186                                      MSG_PRINTER_NOTIFY2, NULL);
187
188                 /* Tell the connections db we're no longer interested in
189                  * printer notify messages. */
190
191                 serverid_register_msg_flags(
192                         messaging_server_id(smbd_messaging_context()),
193                         false, FLAG_MSG_PRINT_NOTIFY);
194         }
195
196         smb_connections--;
197 }
198
199 /****************************************************************************
200  Functions to free a printer entry datastruct.
201 ****************************************************************************/
202
203 static int printer_entry_destructor(Printer_entry *Printer)
204 {
205         if (Printer->notify.client_connected == true) {
206                 int snum = -1;
207
208                 if ( Printer->printer_type == SPLHND_SERVER) {
209                         snum = -1;
210                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
211                 } else if (Printer->printer_type == SPLHND_PRINTER) {
212                         snum = print_queue_snum(Printer->sharename);
213                         if (snum != -1)
214                                 srv_spoolss_replycloseprinter(snum,
215                                                 &Printer->notify.client_hnd);
216                 }
217         }
218
219         Printer->notify.flags=0;
220         Printer->notify.options=0;
221         Printer->notify.localmachine[0]='\0';
222         Printer->notify.printerlocal=0;
223         TALLOC_FREE(Printer->notify.option);
224         Printer->notify.client_connected = false;
225
226         TALLOC_FREE(Printer->devmode);
227         free_a_printer( &Printer->printer_info, 2 );
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  Internal routine for storing printerdata
2030  ***************************************************************************/
2031
2032 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2033                           const char *key, const char *value,
2034                           uint32_t type, uint8_t *data, int real_len)
2035 {
2036         /* the registry objects enforce uniqueness based on value name */
2037
2038         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2039 }
2040
2041 /********************************************************************
2042  GetPrinterData on a printer server Handle.
2043 ********************************************************************/
2044
2045 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2046                                             const char *value,
2047                                             enum winreg_Type *type,
2048                                             union spoolss_PrinterData *data)
2049 {
2050         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2051
2052         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2053                 *type = REG_DWORD;
2054                 data->value = 0x00;
2055                 return WERR_OK;
2056         }
2057
2058         if (!StrCaseCmp(value, "BeepEnabled")) {
2059                 *type = REG_DWORD;
2060                 data->value = 0x00;
2061                 return WERR_OK;
2062         }
2063
2064         if (!StrCaseCmp(value, "EventLog")) {
2065                 *type = REG_DWORD;
2066                 /* formally was 0x1b */
2067                 data->value = 0x00;
2068                 return WERR_OK;
2069         }
2070
2071         if (!StrCaseCmp(value, "NetPopup")) {
2072                 *type = REG_DWORD;
2073                 data->value = 0x00;
2074                 return WERR_OK;
2075         }
2076
2077         if (!StrCaseCmp(value, "MajorVersion")) {
2078                 *type = REG_DWORD;
2079
2080                 /* Windows NT 4.0 seems to not allow uploading of drivers
2081                    to a server that reports 0x3 as the MajorVersion.
2082                    need to investigate more how Win2k gets around this .
2083                    -- jerry */
2084
2085                 if (RA_WINNT == get_remote_arch()) {
2086                         data->value = 0x02;
2087                 } else {
2088                         data->value = 0x03;
2089                 }
2090
2091                 return WERR_OK;
2092         }
2093
2094         if (!StrCaseCmp(value, "MinorVersion")) {
2095                 *type = REG_DWORD;
2096                 data->value = 0x00;
2097                 return WERR_OK;
2098         }
2099
2100         /* REG_BINARY
2101          *  uint32_t size        = 0x114
2102          *  uint32_t major       = 5
2103          *  uint32_t minor       = [0|1]
2104          *  uint32_t build       = [2195|2600]
2105          *  extra unicode string = e.g. "Service Pack 3"
2106          */
2107         if (!StrCaseCmp(value, "OSVersion")) {
2108                 DATA_BLOB blob;
2109                 enum ndr_err_code ndr_err;
2110                 struct spoolss_OSVersion os;
2111
2112                 os.major                = 5;    /* Windows 2000 == 5.0 */
2113                 os.minor                = 0;
2114                 os.build                = 2195; /* build */
2115                 os.extra_string         = "";   /* leave extra string empty */
2116
2117                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2118                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2119                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2120                         return WERR_GENERAL_FAILURE;
2121                 }
2122
2123                 *type = REG_BINARY;
2124                 data->binary = blob;
2125
2126                 return WERR_OK;
2127         }
2128
2129
2130         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2131                 *type = REG_SZ;
2132
2133                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2134                 W_ERROR_HAVE_NO_MEMORY(data->string);
2135
2136                 return WERR_OK;
2137         }
2138
2139         if (!StrCaseCmp(value, "Architecture")) {
2140                 *type = REG_SZ;
2141                 data->string = talloc_strdup(mem_ctx,
2142                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2143                 W_ERROR_HAVE_NO_MEMORY(data->string);
2144
2145                 return WERR_OK;
2146         }
2147
2148         if (!StrCaseCmp(value, "DsPresent")) {
2149                 *type = REG_DWORD;
2150
2151                 /* only show the publish check box if we are a
2152                    member of a AD domain */
2153
2154                 if (lp_security() == SEC_ADS) {
2155                         data->value = 0x01;
2156                 } else {
2157                         data->value = 0x00;
2158                 }
2159                 return WERR_OK;
2160         }
2161
2162         if (!StrCaseCmp(value, "DNSMachineName")) {
2163                 const char *hostname = get_mydnsfullname();
2164
2165                 if (!hostname) {
2166                         return WERR_BADFILE;
2167                 }
2168
2169                 *type = REG_SZ;
2170                 data->string = talloc_strdup(mem_ctx, hostname);
2171                 W_ERROR_HAVE_NO_MEMORY(data->string);
2172
2173                 return WERR_OK;
2174         }
2175
2176         *type = REG_NONE;
2177
2178         return WERR_INVALID_PARAM;
2179 }
2180
2181 /****************************************************************
2182  _spoolss_GetPrinterData
2183 ****************************************************************/
2184
2185 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2186                                struct spoolss_GetPrinterData *r)
2187 {
2188         struct spoolss_GetPrinterDataEx r2;
2189
2190         r2.in.handle            = r->in.handle;
2191         r2.in.key_name          = "PrinterDriverData";
2192         r2.in.value_name        = r->in.value_name;
2193         r2.in.offered           = r->in.offered;
2194         r2.out.type             = r->out.type;
2195         r2.out.data             = r->out.data;
2196         r2.out.needed           = r->out.needed;
2197
2198         return _spoolss_GetPrinterDataEx(p, &r2);
2199 }
2200
2201 /*********************************************************
2202  Connect to the client machine.
2203 **********************************************************/
2204
2205 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2206                         struct sockaddr_storage *client_ss, const char *remote_machine)
2207 {
2208         NTSTATUS ret;
2209         struct cli_state *the_cli;
2210         struct sockaddr_storage rm_addr;
2211         char addr[INET6_ADDRSTRLEN];
2212
2213         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2214                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2215                         remote_machine));
2216                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2217                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2218                         return false;
2219                 }
2220                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2221         } else {
2222                 rm_addr = *client_ss;
2223                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2224                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2225                         addr));
2226         }
2227
2228         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2229                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2230                         addr));
2231                 return false;
2232         }
2233
2234         /* setup the connection */
2235         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2236                 &rm_addr, 0, "IPC$", "IPC",
2237                 "", /* username */
2238                 "", /* domain */
2239                 "", /* password */
2240                 0, lp_client_signing(), NULL );
2241
2242         if ( !NT_STATUS_IS_OK( ret ) ) {
2243                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2244                         remote_machine ));
2245                 return false;
2246         }
2247
2248         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2249                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2250                 cli_shutdown(the_cli);
2251                 return false;
2252         }
2253
2254         /*
2255          * Ok - we have an anonymous connection to the IPC$ share.
2256          * Now start the NT Domain stuff :-).
2257          */
2258
2259         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2260         if (!NT_STATUS_IS_OK(ret)) {
2261                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2262                         remote_machine, nt_errstr(ret)));
2263                 cli_shutdown(the_cli);
2264                 return false;
2265         }
2266
2267         return true;
2268 }
2269
2270 /***************************************************************************
2271  Connect to the client.
2272 ****************************************************************************/
2273
2274 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2275                                         uint32_t localprinter, uint32_t type,
2276                                         struct policy_handle *handle,
2277                                         struct sockaddr_storage *client_ss)
2278 {
2279         WERROR result;
2280         NTSTATUS status;
2281
2282         /*
2283          * If it's the first connection, contact the client
2284          * and connect to the IPC$ share anonymously
2285          */
2286         if (smb_connections==0) {
2287                 fstring unix_printer;
2288
2289                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2290
2291                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2292                         return false;
2293
2294                 messaging_register(smbd_messaging_context(), NULL,
2295                                    MSG_PRINTER_NOTIFY2,
2296                                    receive_notify2_message_list);
2297                 /* Tell the connections db we're now interested in printer
2298                  * notify messages. */
2299                 serverid_register_msg_flags(
2300                         messaging_server_id(smbd_messaging_context()),
2301                         true, FLAG_MSG_PRINT_NOTIFY);
2302         }
2303
2304         /*
2305          * Tell the specific printing tdb we want messages for this printer
2306          * by registering our PID.
2307          */
2308
2309         if (!print_notify_register_pid(snum))
2310                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2311
2312         smb_connections++;
2313
2314         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2315                                                  printer,
2316                                                  localprinter,
2317                                                  type,
2318                                                  0,
2319                                                  NULL,
2320                                                  handle,
2321                                                  &result);
2322         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2323                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2324                         win_errstr(result)));
2325
2326         return (W_ERROR_IS_OK(result));
2327 }
2328
2329 /****************************************************************
2330  ****************************************************************/
2331
2332 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2333                                                              const struct spoolss_NotifyOption *r)
2334 {
2335         struct spoolss_NotifyOption *option;
2336         uint32_t i,k;
2337
2338         if (!r) {
2339                 return NULL;
2340         }
2341
2342         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2343         if (!option) {
2344                 return NULL;
2345         }
2346
2347         *option = *r;
2348
2349         if (!option->count) {
2350                 return option;
2351         }
2352
2353         option->types = talloc_zero_array(option,
2354                 struct spoolss_NotifyOptionType, option->count);
2355         if (!option->types) {
2356                 talloc_free(option);
2357                 return NULL;
2358         }
2359
2360         for (i=0; i < option->count; i++) {
2361                 option->types[i] = r->types[i];
2362
2363                 if (option->types[i].count) {
2364                         option->types[i].fields = talloc_zero_array(option,
2365                                 union spoolss_Field, option->types[i].count);
2366                         if (!option->types[i].fields) {
2367                                 talloc_free(option);
2368                                 return NULL;
2369                         }
2370                         for (k=0; k<option->types[i].count; k++) {
2371                                 option->types[i].fields[k] =
2372                                         r->types[i].fields[k];
2373                         }
2374                 }
2375         }
2376
2377         return option;
2378 }
2379
2380 /****************************************************************
2381  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2382  *
2383  * before replying OK: status=0 a rpc call is made to the workstation
2384  * asking ReplyOpenPrinter
2385  *
2386  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2387  * called from api_spoolss_rffpcnex
2388 ****************************************************************/
2389
2390 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2391                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2392 {
2393         int snum = -1;
2394         struct spoolss_NotifyOption *option = r->in.notify_options;
2395         struct sockaddr_storage client_ss;
2396
2397         /* store the notify value in the printer struct */
2398
2399         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2400
2401         if (!Printer) {
2402                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2403                         "Invalid handle (%s:%u:%u).\n",
2404                         OUR_HANDLE(r->in.handle)));
2405                 return WERR_BADFID;
2406         }
2407
2408         Printer->notify.flags           = r->in.flags;
2409         Printer->notify.options         = r->in.options;
2410         Printer->notify.printerlocal    = r->in.printer_local;
2411
2412         TALLOC_FREE(Printer->notify.option);
2413         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2414
2415         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2416
2417         /* Connect to the client machine and send a ReplyOpenPrinter */
2418
2419         if ( Printer->printer_type == SPLHND_SERVER)
2420                 snum = -1;
2421         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2422                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2423                 return WERR_BADFID;
2424
2425         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2426                 "client_address is %s\n", p->client_address));
2427
2428         if (!interpret_string_addr(&client_ss, p->client_address,
2429                                    AI_NUMERICHOST)) {
2430                 return WERR_SERVER_UNAVAILABLE;
2431         }
2432
2433         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2434                                         Printer->notify.printerlocal, 1,
2435                                         &Printer->notify.client_hnd, &client_ss))
2436                 return WERR_SERVER_UNAVAILABLE;
2437
2438         Printer->notify.client_connected = true;
2439
2440         return WERR_OK;
2441 }
2442
2443 /*******************************************************************
2444  * fill a notify_info_data with the servername
2445  ********************************************************************/
2446
2447 static void spoolss_notify_server_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         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2454 }
2455
2456 /*******************************************************************
2457  * fill a notify_info_data with the printername (not including the servername).
2458  ********************************************************************/
2459
2460 static void spoolss_notify_printer_name(int snum,
2461                                         struct spoolss_Notify *data,
2462                                         print_queue_struct *queue,
2463                                         struct spoolss_PrinterInfo2 *pinfo2,
2464                                         TALLOC_CTX *mem_ctx)
2465 {
2466         /* the notify name should not contain the \\server\ part */
2467         const char *p = strrchr(pinfo2->printername, '\\');
2468
2469         if (!p) {
2470                 p = pinfo2->printername;
2471         } else {
2472                 p++;
2473         }
2474
2475         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2476 }
2477
2478 /*******************************************************************
2479  * fill a notify_info_data with the servicename
2480  ********************************************************************/
2481
2482 static void spoolss_notify_share_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, lp_servicename(snum));
2489 }
2490
2491 /*******************************************************************
2492  * fill a notify_info_data with the port name
2493  ********************************************************************/
2494
2495 static void spoolss_notify_port_name(int snum,
2496                                      struct spoolss_Notify *data,
2497                                      print_queue_struct *queue,
2498                                      struct spoolss_PrinterInfo2 *pinfo2,
2499                                      TALLOC_CTX *mem_ctx)
2500 {
2501         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2502 }
2503
2504 /*******************************************************************
2505  * fill a notify_info_data with the printername
2506  * but it doesn't exist, have to see what to do
2507  ********************************************************************/
2508
2509 static void spoolss_notify_driver_name(int snum,
2510                                        struct spoolss_Notify *data,
2511                                        print_queue_struct *queue,
2512                                        struct spoolss_PrinterInfo2 *pinfo2,
2513                                        TALLOC_CTX *mem_ctx)
2514 {
2515         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2516 }
2517
2518 /*******************************************************************
2519  * fill a notify_info_data with the comment
2520  ********************************************************************/
2521
2522 static void spoolss_notify_comment(int snum,
2523                                    struct spoolss_Notify *data,
2524                                    print_queue_struct *queue,
2525                                    struct spoolss_PrinterInfo2 *pinfo2,
2526                                    TALLOC_CTX *mem_ctx)
2527 {
2528         const char *p;
2529
2530         if (*pinfo2->comment == '\0') {
2531                 p = lp_comment(snum);
2532         } else {
2533                 p = pinfo2->comment;
2534         }
2535
2536         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2537 }
2538
2539 /*******************************************************************
2540  * fill a notify_info_data with the comment
2541  * location = "Room 1, floor 2, building 3"
2542  ********************************************************************/
2543
2544 static void spoolss_notify_location(int snum,
2545                                     struct spoolss_Notify *data,
2546                                     print_queue_struct *queue,
2547                                     struct spoolss_PrinterInfo2 *pinfo2,
2548                                     TALLOC_CTX *mem_ctx)
2549 {
2550         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2551 }
2552
2553 /*******************************************************************
2554  * fill a notify_info_data with the device mode
2555  * jfm:xxxx don't to it for know but that's a real problem !!!
2556  ********************************************************************/
2557
2558 static void spoolss_notify_devmode(int snum,
2559                                    struct spoolss_Notify *data,
2560                                    print_queue_struct *queue,
2561                                    struct spoolss_PrinterInfo2 *pinfo2,
2562                                    TALLOC_CTX *mem_ctx)
2563 {
2564         /* for a dummy implementation we have to zero the fields */
2565         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2566 }
2567
2568 /*******************************************************************
2569  * fill a notify_info_data with the separator file name
2570  ********************************************************************/
2571
2572 static void spoolss_notify_sepfile(int snum,
2573                                    struct spoolss_Notify *data,
2574                                    print_queue_struct *queue,
2575                                    struct spoolss_PrinterInfo2 *pinfo2,
2576                                    TALLOC_CTX *mem_ctx)
2577 {
2578         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2579 }
2580
2581 /*******************************************************************
2582  * fill a notify_info_data with the print processor
2583  * jfm:xxxx return always winprint to indicate we don't do anything to it
2584  ********************************************************************/
2585
2586 static void spoolss_notify_print_processor(int snum,
2587                                            struct spoolss_Notify *data,
2588                                            print_queue_struct *queue,
2589                                            struct spoolss_PrinterInfo2 *pinfo2,
2590                                            TALLOC_CTX *mem_ctx)
2591 {
2592         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2593 }
2594
2595 /*******************************************************************
2596  * fill a notify_info_data with the print processor options
2597  * jfm:xxxx send an empty string
2598  ********************************************************************/
2599
2600 static void spoolss_notify_parameters(int snum,
2601                                       struct spoolss_Notify *data,
2602                                       print_queue_struct *queue,
2603                                       struct spoolss_PrinterInfo2 *pinfo2,
2604                                       TALLOC_CTX *mem_ctx)
2605 {
2606         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2607 }
2608
2609 /*******************************************************************
2610  * fill a notify_info_data with the data type
2611  * jfm:xxxx always send RAW as data type
2612  ********************************************************************/
2613
2614 static void spoolss_notify_datatype(int snum,
2615                                     struct spoolss_Notify *data,
2616                                     print_queue_struct *queue,
2617                                     struct spoolss_PrinterInfo2 *pinfo2,
2618                                     TALLOC_CTX *mem_ctx)
2619 {
2620         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2621 }
2622
2623 /*******************************************************************
2624  * fill a notify_info_data with the security descriptor
2625  * jfm:xxxx send an null pointer to say no security desc
2626  * have to implement security before !
2627  ********************************************************************/
2628
2629 static void spoolss_notify_security_desc(int snum,
2630                                          struct spoolss_Notify *data,
2631                                          print_queue_struct *queue,
2632                                          struct spoolss_PrinterInfo2 *pinfo2,
2633                                          TALLOC_CTX *mem_ctx)
2634 {
2635         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2636 }
2637
2638 /*******************************************************************
2639  * fill a notify_info_data with the attributes
2640  * jfm:xxxx a samba printer is always shared
2641  ********************************************************************/
2642
2643 static void spoolss_notify_attributes(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->attributes);
2650 }
2651
2652 /*******************************************************************
2653  * fill a notify_info_data with the priority
2654  ********************************************************************/
2655
2656 static void spoolss_notify_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->priority);
2663 }
2664
2665 /*******************************************************************
2666  * fill a notify_info_data with the default priority
2667  ********************************************************************/
2668
2669 static void spoolss_notify_default_priority(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->defaultpriority);
2676 }
2677
2678 /*******************************************************************
2679  * fill a notify_info_data with the start time
2680  ********************************************************************/
2681
2682 static void spoolss_notify_start_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->starttime);
2689 }
2690
2691 /*******************************************************************
2692  * fill a notify_info_data with the until time
2693  ********************************************************************/
2694
2695 static void spoolss_notify_until_time(int snum,
2696                                       struct spoolss_Notify *data,
2697                                       print_queue_struct *queue,
2698                                       struct spoolss_PrinterInfo2 *pinfo2,
2699                                       TALLOC_CTX *mem_ctx)
2700 {
2701         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2702 }
2703
2704 /*******************************************************************
2705  * fill a notify_info_data with the status
2706  ********************************************************************/
2707
2708 static void spoolss_notify_status(int snum,
2709                                   struct spoolss_Notify *data,
2710                                   print_queue_struct *queue,
2711                                   struct spoolss_PrinterInfo2 *pinfo2,
2712                                   TALLOC_CTX *mem_ctx)
2713 {
2714         print_status_struct status;
2715
2716         print_queue_length(snum, &status);
2717         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2718 }
2719
2720 /*******************************************************************
2721  * fill a notify_info_data with the number of jobs queued
2722  ********************************************************************/
2723
2724 static void spoolss_notify_cjobs(int snum,
2725                                  struct spoolss_Notify *data,
2726                                  print_queue_struct *queue,
2727                                  struct spoolss_PrinterInfo2 *pinfo2,
2728                                  TALLOC_CTX *mem_ctx)
2729 {
2730         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2731 }
2732
2733 /*******************************************************************
2734  * fill a notify_info_data with the average ppm
2735  ********************************************************************/
2736
2737 static void spoolss_notify_average_ppm(int snum,
2738                                        struct spoolss_Notify *data,
2739                                        print_queue_struct *queue,
2740                                        struct spoolss_PrinterInfo2 *pinfo2,
2741                                        TALLOC_CTX *mem_ctx)
2742 {
2743         /* always respond 8 pages per minutes */
2744         /* a little hard ! */
2745         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2746 }
2747
2748 /*******************************************************************
2749  * fill a notify_info_data with username
2750  ********************************************************************/
2751
2752 static void spoolss_notify_username(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_STRING(data, queue->fs_user);
2759 }
2760
2761 /*******************************************************************
2762  * fill a notify_info_data with job status
2763  ********************************************************************/
2764
2765 static void spoolss_notify_job_status(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_INTEGER(data, nt_printj_status(queue->status));
2772 }
2773
2774 /*******************************************************************
2775  * fill a notify_info_data with job name
2776  ********************************************************************/
2777
2778 static void spoolss_notify_job_name(int snum,
2779                                     struct spoolss_Notify *data,
2780                                     print_queue_struct *queue,
2781                                     struct spoolss_PrinterInfo2 *pinfo2,
2782                                     TALLOC_CTX *mem_ctx)
2783 {
2784         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2785 }
2786
2787 /*******************************************************************
2788  * fill a notify_info_data with job status
2789  ********************************************************************/
2790
2791 static void spoolss_notify_job_status_string(int snum,
2792                                              struct spoolss_Notify *data,
2793                                              print_queue_struct *queue,
2794                                              struct spoolss_PrinterInfo2 *pinfo2,
2795                                              TALLOC_CTX *mem_ctx)
2796 {
2797         /*
2798          * Now we're returning job status codes we just return a "" here. JRA.
2799          */
2800
2801         const char *p = "";
2802
2803 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2804         p = "unknown";
2805
2806         switch (queue->status) {
2807         case LPQ_QUEUED:
2808                 p = "Queued";
2809                 break;
2810         case LPQ_PAUSED:
2811                 p = "";    /* NT provides the paused string */
2812                 break;
2813         case LPQ_SPOOLING:
2814                 p = "Spooling";
2815                 break;
2816         case LPQ_PRINTING:
2817                 p = "Printing";
2818                 break;
2819         }
2820 #endif /* NO LONGER NEEDED. */
2821
2822         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2823 }
2824
2825 /*******************************************************************
2826  * fill a notify_info_data with job time
2827  ********************************************************************/
2828
2829 static void spoolss_notify_job_time(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, 0);
2836 }
2837
2838 /*******************************************************************
2839  * fill a notify_info_data with job size
2840  ********************************************************************/
2841
2842 static void spoolss_notify_job_size(int snum,
2843                                     struct spoolss_Notify *data,
2844                                     print_queue_struct *queue,
2845                                     struct spoolss_PrinterInfo2 *pinfo2,
2846                                     TALLOC_CTX *mem_ctx)
2847 {
2848         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2849 }
2850
2851 /*******************************************************************
2852  * fill a notify_info_data with page info
2853  ********************************************************************/
2854 static void spoolss_notify_total_pages(int snum,
2855                                 struct spoolss_Notify *data,
2856                                 print_queue_struct *queue,
2857                                 struct spoolss_PrinterInfo2 *pinfo2,
2858                                 TALLOC_CTX *mem_ctx)
2859 {
2860         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2861 }
2862
2863 /*******************************************************************
2864  * fill a notify_info_data with pages printed info.
2865  ********************************************************************/
2866 static void spoolss_notify_pages_printed(int snum,
2867                                 struct spoolss_Notify *data,
2868                                 print_queue_struct *queue,
2869                                 struct spoolss_PrinterInfo2 *pinfo2,
2870                                 TALLOC_CTX *mem_ctx)
2871 {
2872         /* Add code when back-end tracks this */
2873         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2874 }
2875
2876 /*******************************************************************
2877  Fill a notify_info_data with job position.
2878  ********************************************************************/
2879
2880 static void spoolss_notify_job_position(int snum,
2881                                         struct spoolss_Notify *data,
2882                                         print_queue_struct *queue,
2883                                         struct spoolss_PrinterInfo2 *pinfo2,
2884                                         TALLOC_CTX *mem_ctx)
2885 {
2886         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2887 }
2888
2889 /*******************************************************************
2890  Fill a notify_info_data with submitted time.
2891  ********************************************************************/
2892
2893 static void spoolss_notify_submitted_time(int snum,
2894                                           struct spoolss_Notify *data,
2895                                           print_queue_struct *queue,
2896                                           struct spoolss_PrinterInfo2 *pinfo2,
2897                                           TALLOC_CTX *mem_ctx)
2898 {
2899         data->data.string.string = NULL;
2900         data->data.string.size = 0;
2901
2902         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2903                                &data->data.string.string,
2904                                &data->data.string.size);
2905
2906 }
2907
2908 struct s_notify_info_data_table
2909 {
2910         enum spoolss_NotifyType type;
2911         uint16_t field;
2912         const char *name;
2913         enum spoolss_NotifyTable variable_type;
2914         void (*fn) (int snum, struct spoolss_Notify *data,
2915                     print_queue_struct *queue,
2916                     struct spoolss_PrinterInfo2 *pinfo2,
2917                     TALLOC_CTX *mem_ctx);
2918 };
2919
2920 /* A table describing the various print notification constants and
2921    whether the notification data is a pointer to a variable sized
2922    buffer, a one value uint32_t or a two value uint32_t. */
2923
2924 static const struct s_notify_info_data_table notify_info_data_table[] =
2925 {
2926 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2927 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2928 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
2929 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2930 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2931 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
2932 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
2933 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2934 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
2935 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2936 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2937 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2938 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
2939 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
2940 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2941 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
2942 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2943 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2944 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
2945 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
2946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
2949 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2950 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
2951 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2952 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2953 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2954 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2955 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
2956 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
2957 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2958 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2959 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2960 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2961 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2962 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
2963 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
2964 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
2965 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
2966 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2967 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
2968 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
2969 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2970 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2971 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
2972 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
2973 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
2974 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
2975 };
2976
2977 /*******************************************************************
2978  Return the variable_type of info_data structure.
2979 ********************************************************************/
2980
2981 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2982                                                   uint16_t field)
2983 {
2984         int i=0;
2985
2986         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2987                 if ( (notify_info_data_table[i].type == type) &&
2988                      (notify_info_data_table[i].field == field) ) {
2989                         return notify_info_data_table[i].variable_type;
2990                 }
2991         }
2992
2993         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2994
2995         return 0;
2996 }
2997
2998 /****************************************************************************
2999 ****************************************************************************/
3000
3001 static bool search_notify(enum spoolss_NotifyType type,
3002                           uint16_t field,
3003                           int *value)
3004 {
3005         int i;
3006
3007         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3008                 if (notify_info_data_table[i].type == type &&
3009                     notify_info_data_table[i].field == field &&
3010                     notify_info_data_table[i].fn != NULL) {
3011                         *value = i;
3012                         return true;
3013                 }
3014         }
3015
3016         return false;
3017 }
3018
3019 /****************************************************************************
3020 ****************************************************************************/
3021
3022 static void construct_info_data(struct spoolss_Notify *info_data,
3023                                 enum spoolss_NotifyType type,
3024                                 uint16_t field, int id)
3025 {
3026         info_data->type                 = type;
3027         info_data->field.field          = field;
3028         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3029         info_data->job_id               = id;
3030 }
3031
3032 /*******************************************************************
3033  *
3034  * fill a notify_info struct with info asked
3035  *
3036  ********************************************************************/
3037
3038 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3039                                           struct spoolss_NotifyInfo *info,
3040                                           struct spoolss_PrinterInfo2 *pinfo2,
3041                                           int snum,
3042                                           const struct spoolss_NotifyOptionType *option_type,
3043                                           uint32_t id,
3044                                           TALLOC_CTX *mem_ctx)
3045 {
3046         int field_num,j;
3047         enum spoolss_NotifyType type;
3048         uint16_t field;
3049
3050         struct spoolss_Notify *current_data;
3051         print_queue_struct *queue=NULL;
3052
3053         type = option_type->type;
3054
3055         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3056                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3057                 option_type->count, lp_servicename(snum)));
3058
3059         for(field_num=0; field_num < option_type->count; field_num++) {
3060                 field = option_type->fields[field_num].field;
3061
3062                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3063
3064                 if (!search_notify(type, field, &j) )
3065                         continue;
3066
3067                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3068                                                       struct spoolss_Notify,
3069                                                       info->count + 1);
3070                 if (info->notifies == NULL) {
3071                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3072                         return false;
3073                 }
3074
3075                 current_data = &info->notifies[info->count];
3076
3077                 construct_info_data(current_data, type, field, id);
3078
3079                 DEBUG(10, ("construct_notify_printer_info: "
3080                            "calling [%s]  snum=%d  printername=[%s])\n",
3081                            notify_info_data_table[j].name, snum,
3082                            pinfo2->printername));
3083
3084                 notify_info_data_table[j].fn(snum, current_data, queue,
3085                                              pinfo2, mem_ctx);
3086
3087                 info->count++;
3088         }
3089
3090         return true;
3091 }
3092
3093 /*******************************************************************
3094  *
3095  * fill a notify_info struct with info asked
3096  *
3097  ********************************************************************/
3098
3099 static bool construct_notify_jobs_info(print_queue_struct *queue,
3100                                        struct spoolss_NotifyInfo *info,
3101                                        struct spoolss_PrinterInfo2 *pinfo2,
3102                                        int snum,
3103                                        const struct spoolss_NotifyOptionType *option_type,
3104                                        uint32_t id,
3105                                        TALLOC_CTX *mem_ctx)
3106 {
3107         int field_num,j;
3108         enum spoolss_NotifyType type;
3109         uint16_t field;
3110         struct spoolss_Notify *current_data;
3111
3112         DEBUG(4,("construct_notify_jobs_info\n"));
3113
3114         type = option_type->type;
3115
3116         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3117                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3118                 option_type->count));
3119
3120         for(field_num=0; field_num<option_type->count; field_num++) {
3121                 field = option_type->fields[field_num].field;
3122
3123                 if (!search_notify(type, field, &j) )
3124                         continue;
3125
3126                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3127                                                       struct spoolss_Notify,
3128                                                       info->count + 1);
3129                 if (info->notifies == NULL) {
3130                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3131                         return false;
3132                 }
3133
3134                 current_data=&(info->notifies[info->count]);
3135
3136                 construct_info_data(current_data, type, field, id);
3137                 notify_info_data_table[j].fn(snum, current_data, queue,
3138                                              pinfo2, mem_ctx);
3139                 info->count++;
3140         }
3141
3142         return true;
3143 }
3144
3145 /*
3146  * JFM: The enumeration is not that simple, it's even non obvious.
3147  *
3148  * let's take an example: I want to monitor the PRINTER SERVER for
3149  * the printer's name and the number of jobs currently queued.
3150  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3151  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3152  *
3153  * I have 3 printers on the back of my server.
3154  *
3155  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3156  * structures.
3157  *   Number     Data                    Id
3158  *      1       printer 1 name          1
3159  *      2       printer 1 cjob          1
3160  *      3       printer 2 name          2
3161  *      4       printer 2 cjob          2
3162  *      5       printer 3 name          3
3163  *      6       printer 3 name          3
3164  *
3165  * that's the print server case, the printer case is even worse.
3166  */
3167
3168 /*******************************************************************
3169  *
3170  * enumerate all printers on the printserver
3171  * fill a notify_info struct with info asked
3172  *
3173  ********************************************************************/
3174
3175 static WERROR printserver_notify_info(pipes_struct *p,
3176                                       struct policy_handle *hnd,
3177                                       struct spoolss_NotifyInfo *info,
3178                                       TALLOC_CTX *mem_ctx)
3179 {
3180         int snum;
3181         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3182         int n_services=lp_numservices();
3183         int i;
3184         struct spoolss_NotifyOption *option;
3185         struct spoolss_NotifyOptionType option_type;
3186         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3187         WERROR result;
3188
3189         DEBUG(4,("printserver_notify_info\n"));
3190
3191         if (!Printer)
3192                 return WERR_BADFID;
3193
3194         option = Printer->notify.option;
3195
3196         info->version   = 2;
3197         info->notifies  = NULL;
3198         info->count     = 0;
3199
3200         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3201            sending a ffpcn() request first */
3202
3203         if ( !option )
3204                 return WERR_BADFID;
3205
3206         for (i=0; i<option->count; i++) {
3207                 option_type = option->types[i];
3208
3209                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3210                         continue;
3211
3212                 for (snum = 0; snum < n_services; snum++) {
3213                         if (!lp_browseable(snum) ||
3214                             !lp_snum_ok(snum) ||
3215                             !lp_print_ok(snum)) {
3216                                 continue; /* skip */
3217                         }
3218
3219                         /* FIXME: should we use a SYSTEM server_info here? */
3220                         result = winreg_get_printer(mem_ctx, p->server_info,
3221                                                     Printer->servername,
3222                                                     lp_servicename(snum),
3223                                                     &pinfo2);
3224                         if (!W_ERROR_IS_OK(result)) {
3225                                 DEBUG(4, ("printserver_notify_info: "
3226                                           "Failed to get printer [%s]\n",
3227                                           lp_servicename(snum)));
3228                                 continue;
3229                         }
3230
3231
3232                         construct_notify_printer_info(Printer, info,
3233                                                       pinfo2, snum,
3234                                                       &option_type, snum,
3235                                                       mem_ctx);
3236
3237                         TALLOC_FREE(pinfo2);
3238                 }
3239         }
3240
3241 #if 0
3242         /*
3243          * Debugging information, don't delete.
3244          */
3245
3246         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3247         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3248         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3249
3250         for (i=0; i<info->count; i++) {
3251                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3252                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3253                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3254         }
3255 #endif
3256
3257         return WERR_OK;
3258 }
3259
3260 /*******************************************************************
3261  *
3262  * fill a notify_info struct with info asked
3263  *
3264  ********************************************************************/
3265
3266 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3267                                   struct spoolss_NotifyInfo *info,
3268                                   TALLOC_CTX *mem_ctx)
3269 {
3270         int snum;
3271         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3272         int i;
3273         uint32_t id;
3274         struct spoolss_NotifyOption *option;
3275         struct spoolss_NotifyOptionType option_type;
3276         int count,j;
3277         print_queue_struct *queue=NULL;
3278         print_status_struct status;
3279         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3280         WERROR result;
3281
3282         DEBUG(4,("printer_notify_info\n"));
3283
3284         if (!Printer)
3285                 return WERR_BADFID;
3286
3287         option = Printer->notify.option;
3288         id = 0x0;
3289
3290         info->version   = 2;
3291         info->notifies  = NULL;
3292         info->count     = 0;
3293
3294         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3295            sending a ffpcn() request first */
3296
3297         if ( !option )
3298                 return WERR_BADFID;
3299
3300         get_printer_snum(p, hnd, &snum, NULL);
3301
3302         /* FIXME: should we use a SYSTEM server_info here ? */
3303         result = winreg_get_printer(mem_ctx, p->server_info,
3304                                     Printer->servername,
3305                                     lp_servicename(snum), &pinfo2);
3306         if (!W_ERROR_IS_OK(result)) {
3307                 return WERR_BADFID;
3308         }
3309
3310         for (i=0; i<option->count; i++) {
3311                 option_type = option->types[i];
3312
3313                 switch (option_type.type) {
3314                 case PRINTER_NOTIFY_TYPE:
3315                         if (construct_notify_printer_info(Printer, info,
3316                                                           pinfo2, snum,
3317                                                           &option_type, id,
3318                                                           mem_ctx)) {
3319                                 id--;
3320                         }
3321                         break;
3322
3323                 case JOB_NOTIFY_TYPE:
3324
3325                         count = print_queue_status(snum, &queue, &status);
3326
3327                         for (j=0; j<count; j++) {
3328                                 construct_notify_jobs_info(&queue[j], info,
3329                                                            pinfo2, snum,
3330                                                            &option_type,
3331                                                            queue[j].job,
3332                                                            mem_ctx);
3333                         }
3334
3335                         SAFE_FREE(queue);
3336                         break;
3337                 }
3338         }
3339
3340         /*
3341          * Debugging information, don't delete.
3342          */
3343         /*
3344         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3345         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3346         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3347
3348         for (i=0; i<info->count; i++) {
3349                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3350                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3351                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3352         }
3353         */
3354
3355         talloc_free(pinfo2);
3356         return WERR_OK;
3357 }
3358
3359 /****************************************************************
3360  _spoolss_RouterRefreshPrinterChangeNotify
3361 ****************************************************************/
3362
3363 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3364                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3365 {
3366         struct spoolss_NotifyInfo *info;
3367
3368         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3369         WERROR result = WERR_BADFID;
3370
3371         /* we always have a spoolss_NotifyInfo struct */
3372         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3373         if (!info) {
3374                 result = WERR_NOMEM;
3375                 goto done;
3376         }
3377
3378         *r->out.info = info;
3379
3380         if (!Printer) {
3381                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3382                         "Invalid handle (%s:%u:%u).\n",
3383                         OUR_HANDLE(r->in.handle)));
3384                 goto done;
3385         }
3386
3387         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3388
3389         /*
3390          *      We are now using the change value, and
3391          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3392          *      I don't have a global notification system, I'm sending back all the
3393          *      informations even when _NOTHING_ has changed.
3394          */
3395
3396         /* We need to keep track of the change value to send back in
3397            RRPCN replies otherwise our updates are ignored. */
3398
3399         Printer->notify.fnpcn = true;
3400
3401         if (Printer->notify.client_connected) {
3402                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3403                         "Saving change value in request [%x]\n",
3404                         r->in.change_low));
3405                 Printer->notify.change = r->in.change_low;
3406         }
3407
3408         /* just ignore the spoolss_NotifyOption */
3409
3410         switch (Printer->printer_type) {
3411                 case SPLHND_SERVER:
3412                         result = printserver_notify_info(p, r->in.handle,
3413                                                          info, p->mem_ctx);
3414                         break;
3415
3416                 case SPLHND_PRINTER:
3417                         result = printer_notify_info(p, r->in.handle,
3418                                                      info, p->mem_ctx);
3419                         break;
3420         }
3421
3422         Printer->notify.fnpcn = false;
3423
3424 done:
3425         return result;
3426 }
3427
3428 /********************************************************************
3429  * construct_printer_info_0
3430  * fill a printer_info_0 struct
3431  ********************************************************************/
3432
3433 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3434                                       struct auth_serversupplied_info *server_info,
3435                                       struct spoolss_PrinterInfo2 *info2,
3436                                       struct spoolss_PrinterInfo0 *r,
3437                                       int snum)
3438 {
3439         int count;
3440         counter_printer_0 *session_counter;
3441         struct timeval setuptime;
3442         print_status_struct status;
3443
3444         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3445         W_ERROR_HAVE_NO_MEMORY(r->printername);
3446
3447         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3448         W_ERROR_HAVE_NO_MEMORY(r->servername);
3449
3450         count = print_queue_length(snum, &status);
3451
3452         /* check if we already have a counter for this printer */
3453         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3454                 if (session_counter->snum == snum)
3455                         break;
3456         }
3457
3458         /* it's the first time, add it to the list */
3459         if (session_counter == NULL) {
3460                 session_counter = SMB_MALLOC_P(counter_printer_0);
3461                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3462                 ZERO_STRUCTP(session_counter);
3463                 session_counter->snum           = snum;
3464                 session_counter->counter        = 0;
3465                 DLIST_ADD(counter_list, session_counter);
3466         }
3467
3468         /* increment it */
3469         session_counter->counter++;
3470
3471         r->cjobs                        = count;
3472         r->total_jobs                   = 0;
3473         r->total_bytes                  = 0;
3474
3475         get_startup_time(&setuptime);
3476         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3477
3478         /* JFM:
3479          * the global_counter should be stored in a TDB as it's common to all the clients
3480          * and should be zeroed on samba startup
3481          */
3482         r->global_counter               = session_counter->counter;
3483         r->total_pages                  = 0;
3484         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3485         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3486         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3487         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3488         r->spooling                     = 0;
3489         r->max_spooling                 = 0;
3490         r->session_counter              = session_counter->counter;
3491         r->num_error_out_of_paper       = 0x0;
3492         r->num_error_not_ready          = 0x0;          /* number of print failure */
3493         r->job_error                    = 0x0;
3494         r->number_of_processors         = 0x1;
3495         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3496         r->high_part_total_bytes        = 0x0;
3497         winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3498         r->last_error                   = WERR_OK;
3499         r->status                       = nt_printq_status(status.status);
3500         r->enumerate_network_printers   = 0x0;
3501         r->c_setprinter                 = 0x0;
3502         r->processor_architecture       = 0x0;
3503         r->processor_level              = 0x6;          /* 6  ???*/
3504         r->ref_ic                       = 0;
3505         r->reserved2                    = 0;
3506         r->reserved3                    = 0;
3507
3508         return WERR_OK;
3509 }
3510
3511
3512 /********************************************************************
3513  * construct_printer_info1
3514  * fill a spoolss_PrinterInfo1 struct
3515 ********************************************************************/
3516
3517 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3518                                       const struct spoolss_PrinterInfo2 *info2,
3519                                       uint32_t flags,
3520                                       struct spoolss_PrinterInfo1 *r,
3521                                       int snum)
3522 {
3523         r->flags                = flags;
3524
3525         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3526                                                   info2->printername,
3527                                                   info2->drivername,
3528                                                   info2->location);
3529         W_ERROR_HAVE_NO_MEMORY(r->description);
3530
3531         if (info2->comment == NULL || info2->comment[0] == '\0') {
3532                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3533         } else {
3534                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3535         }
3536         W_ERROR_HAVE_NO_MEMORY(r->comment);
3537
3538         r->name                 = talloc_strdup(mem_ctx, info2->printername);
3539         W_ERROR_HAVE_NO_MEMORY(r->name);
3540
3541         return WERR_OK;
3542 }
3543
3544 /********************************************************************
3545  * construct_printer_info2
3546  * fill a spoolss_PrinterInfo2 struct
3547 ********************************************************************/
3548
3549 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3550                                       const struct spoolss_PrinterInfo2 *info2,
3551                                       struct spoolss_PrinterInfo2 *r,
3552                                       int snum)
3553 {
3554         int count;
3555         print_status_struct status;
3556
3557         count = print_queue_length(snum, &status);
3558
3559         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3560         W_ERROR_HAVE_NO_MEMORY(r->servername);
3561         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3562         W_ERROR_HAVE_NO_MEMORY(r->printername);
3563         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3564         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3565         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3566         W_ERROR_HAVE_NO_MEMORY(r->portname);
3567         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3568         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3569
3570         if (info2->comment[0] == '\0') {
3571                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3572         } else {
3573                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3574         }
3575         W_ERROR_HAVE_NO_MEMORY(r->comment);
3576
3577         r->location             = talloc_strdup(mem_ctx, info2->location);
3578         W_ERROR_HAVE_NO_MEMORY(r->location);
3579         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3580         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3581         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3582         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3583         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3584         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3585         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3586         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3587
3588         r->attributes           = info2->attributes;
3589
3590         r->priority             = info2->priority;
3591         r->defaultpriority      = info2->defaultpriority;
3592         r->starttime            = info2->starttime;
3593         r->untiltime            = info2->untiltime;
3594         r->status               = nt_printq_status(status.status);
3595         r->cjobs                = count;
3596         r->averageppm           = info2->averageppm;
3597
3598         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3599         if (!r->devmode) {
3600                 DEBUG(8,("Returning NULL Devicemode!\n"));
3601         }
3602
3603         r->secdesc = NULL;
3604
3605         if (info2->secdesc != NULL) {
3606                 /* don't use talloc_steal() here unless you do a deep steal of all
3607                    the SEC_DESC members */
3608
3609                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
3610         }
3611
3612         return WERR_OK;
3613 }
3614
3615 /********************************************************************
3616  * construct_printer_info3
3617  * fill a spoolss_PrinterInfo3 struct
3618  ********************************************************************/
3619
3620 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3621                                       const struct spoolss_PrinterInfo2 *info2,
3622                                       struct spoolss_PrinterInfo3 *r,
3623                                       int snum)
3624 {
3625         /* These are the components of the SD we are returning. */
3626
3627         if (info2->secdesc != NULL) {
3628                 /* don't use talloc_steal() here unless you do a deep steal of all
3629                    the SEC_DESC members */
3630
3631                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3632                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3633         }
3634
3635         return WERR_OK;
3636 }
3637
3638 /********************************************************************
3639  * construct_printer_info4
3640  * fill a spoolss_PrinterInfo4 struct
3641  ********************************************************************/
3642
3643 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3644                                       const struct spoolss_PrinterInfo2 *info2,
3645                                       struct spoolss_PrinterInfo4 *r,
3646                                       int snum)
3647 {
3648         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3649         W_ERROR_HAVE_NO_MEMORY(r->printername);
3650         r->servername   = talloc_strdup(mem_ctx, info2->servername);
3651         W_ERROR_HAVE_NO_MEMORY(r->servername);
3652
3653         r->attributes   = info2->attributes;
3654
3655         return WERR_OK;
3656 }
3657
3658 /********************************************************************
3659  * construct_printer_info5
3660  * fill a spoolss_PrinterInfo5 struct
3661  ********************************************************************/
3662
3663 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3664                                       const struct spoolss_PrinterInfo2 *info2,
3665                                       struct spoolss_PrinterInfo5 *r,
3666                                       int snum)
3667 {
3668         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3669         W_ERROR_HAVE_NO_MEMORY(r->printername);
3670         r->portname     = talloc_strdup(mem_ctx, info2->portname);
3671         W_ERROR_HAVE_NO_MEMORY(r->portname);
3672
3673         r->attributes   = info2->attributes;
3674
3675         /* these two are not used by NT+ according to MSDN */
3676         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3677         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3678
3679         return WERR_OK;
3680 }
3681
3682 /********************************************************************
3683  * construct_printer_info_6
3684  * fill a spoolss_PrinterInfo6 struct
3685  ********************************************************************/
3686
3687 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3688                                       const struct spoolss_PrinterInfo2 *info2,
3689                                       struct spoolss_PrinterInfo6 *r,
3690                                       int snum)
3691 {
3692         int count;
3693         print_status_struct status;
3694
3695         count = print_queue_length(snum, &status);
3696
3697         r->status = nt_printq_status(status.status);
3698
3699         return WERR_OK;
3700 }
3701
3702 /********************************************************************
3703  * construct_printer_info7
3704  * fill a spoolss_PrinterInfo7 struct
3705  ********************************************************************/
3706
3707 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3708                                       Printer_entry *print_hnd,
3709                                       struct spoolss_PrinterInfo7 *r,
3710                                       int snum)
3711 {
3712         struct auth_serversupplied_info *server_info;
3713         struct GUID guid;
3714         NTSTATUS status;
3715
3716         status = make_server_info_system(mem_ctx, &server_info);
3717         if (!NT_STATUS_IS_OK(status)) {
3718                 DEBUG(0, ("construct_printer_info7: "
3719                           "Could not create system server_info\n"));
3720                 return WERR_NOMEM;
3721         }
3722
3723         if (is_printer_published(mem_ctx, server_info, print_hnd->servername,
3724                                  lp_servicename(snum), &guid, NULL)) {
3725                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3726                 r->action = DSPRINT_PUBLISH;
3727         } else {
3728                 r->guid = talloc_strdup(mem_ctx, "");
3729                 r->action = DSPRINT_UNPUBLISH;
3730         }
3731         W_ERROR_HAVE_NO_MEMORY(r->guid);
3732
3733         TALLOC_FREE(server_info);
3734         return WERR_OK;
3735 }
3736
3737 /********************************************************************
3738  * construct_printer_info8
3739  * fill a spoolss_PrinterInfo8 struct
3740  ********************************************************************/
3741
3742 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3743                                       const struct spoolss_PrinterInfo2 *info2,
3744                                       struct spoolss_DeviceModeInfo *r,
3745                                       int snum)
3746 {
3747         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3748         if (!r->devmode) {
3749                 DEBUG(8,("Returning NULL Devicemode!\n"));
3750         }
3751
3752         return WERR_OK;
3753 }
3754
3755
3756 /********************************************************************
3757 ********************************************************************/
3758
3759 static bool snum_is_shared_printer(int snum)
3760 {
3761         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3762 }
3763
3764 /********************************************************************
3765  Spoolss_enumprinters.
3766 ********************************************************************/
3767
3768 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3769                                            struct auth_serversupplied_info *server_info,
3770                                            uint32_t level,
3771                                            uint32_t flags,
3772                                            union spoolss_PrinterInfo **info_p,
3773                                            uint32_t *count_p)
3774 {
3775         int snum;
3776         int n_services = lp_numservices();
3777         union spoolss_PrinterInfo *info = NULL;
3778         uint32_t count = 0;
3779         WERROR result = WERR_OK;
3780
3781         *count_p = 0;
3782         *info_p = NULL;
3783
3784         for (snum = 0; snum < n_services; snum++) {
3785
3786                 const char *printer;
3787                 struct spoolss_PrinterInfo2 *info2;
3788
3789                 if (!snum_is_shared_printer(snum)) {
3790                         continue;
3791                 }
3792
3793                 printer = lp_const_servicename(snum);
3794
3795                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3796                         printer, snum));
3797
3798                 result = winreg_create_printer(mem_ctx,
3799                                                server_info,
3800                                                NULL,
3801                                                printer);
3802                 if (!W_ERROR_IS_OK(result)) {
3803                         goto out;
3804                 }
3805
3806                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3807                                             union spoolss_PrinterInfo,
3808                                             count + 1);
3809                 if (!info) {
3810                         result = WERR_NOMEM;
3811                         goto out;
3812                 }
3813
3814                 result = winreg_get_printer(mem_ctx, server_info,
3815                                             NULL, printer, &info2);
3816                 if (!W_ERROR_IS_OK(result)) {
3817                         goto out;
3818                 }
3819
3820                 switch (level) {
3821                 case 0:
3822                         result = construct_printer_info0(info, server_info, info2,
3823                                                          &info[count].info0, snum);
3824                         break;
3825                 case 1:
3826                         result = construct_printer_info1(info, info2, flags,
3827                                                          &info[count].info1, snum);
3828                         break;
3829                 case 2:
3830                         result = construct_printer_info2(info, info2,
3831                                                          &info[count].info2, snum);
3832                         break;
3833                 case 4:
3834                         result = construct_printer_info4(info, info2,
3835                                                          &info[count].info4, snum);
3836                         break;
3837                 case 5:
3838                         result = construct_printer_info5(info, info2,
3839                                                          &info[count].info5, snum);
3840                         break;
3841
3842                 default:
3843                         result = WERR_UNKNOWN_LEVEL;
3844                         goto out;
3845                 }
3846
3847                 if (!W_ERROR_IS_OK(result)) {
3848                         goto out;
3849                 }
3850
3851                 count++;
3852         }
3853
3854         *count_p = count;
3855         *info_p = info;
3856
3857  out:
3858         if (!W_ERROR_IS_OK(result)) {
3859                 TALLOC_FREE(info);
3860                 return result;
3861         }
3862
3863         *info_p = info;
3864
3865         return WERR_OK;
3866 }
3867
3868 /********************************************************************
3869  * handle enumeration of printers at level 0
3870  ********************************************************************/
3871
3872 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3873                                   struct auth_serversupplied_info *server_info,
3874                                   uint32_t flags,
3875                                   const char *servername,
3876                                   union spoolss_PrinterInfo **info,
3877                                   uint32_t *count)
3878 {
3879         DEBUG(4,("enum_all_printers_info_0\n"));
3880
3881         return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3882 }
3883
3884
3885 /********************************************************************
3886 ********************************************************************/
3887
3888 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3889                                        struct auth_serversupplied_info *server_info,
3890                                        uint32_t flags,
3891                                        union spoolss_PrinterInfo **info,
3892                                        uint32_t *count)
3893 {
3894         DEBUG(4,("enum_all_printers_info_1\n"));
3895
3896         return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3897 }
3898
3899 /********************************************************************
3900  enum_all_printers_info_1_local.
3901 *********************************************************************/
3902
3903 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3904                                              struct auth_serversupplied_info *server_info,
3905                                              union spoolss_PrinterInfo **info,
3906                                              uint32_t *count)
3907 {
3908         DEBUG(4,("enum_all_printers_info_1_local\n"));
3909
3910         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3911 }
3912
3913 /********************************************************************
3914  enum_all_printers_info_1_name.
3915 *********************************************************************/
3916
3917 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3918                                             struct auth_serversupplied_info *server_info,
3919                                             const char *name,
3920                                             union spoolss_PrinterInfo **info,
3921                                             uint32_t *count)
3922 {
3923         const char *s = name;
3924
3925         DEBUG(4,("enum_all_printers_info_1_name\n"));
3926
3927         if ((name[0] == '\\') && (name[1] == '\\')) {
3928                 s = name + 2;
3929         }
3930
3931         if (!is_myname_or_ipaddr(s)) {
3932                 return WERR_INVALID_NAME;
3933         }
3934
3935         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3936 }
3937
3938 /********************************************************************
3939  enum_all_printers_info_1_network.
3940 *********************************************************************/
3941
3942 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3943                                                struct auth_serversupplied_info *server_info,
3944                                                const char *name,
3945                                                union spoolss_PrinterInfo **info,
3946                                                uint32_t *count)
3947 {
3948         const char *s = name;
3949
3950         DEBUG(4,("enum_all_printers_info_1_network\n"));
3951
3952         /* If we respond to a enum_printers level 1 on our name with flags
3953            set to PRINTER_ENUM_REMOTE with a list of printers then these
3954            printers incorrectly appear in the APW browse list.
3955            Specifically the printers for the server appear at the workgroup
3956            level where all the other servers in the domain are
3957            listed. Windows responds to this call with a
3958            WERR_CAN_NOT_COMPLETE so we should do the same. */
3959
3960         if (name[0] == '\\' && name[1] == '\\') {
3961                  s = name + 2;
3962         }
3963
3964         if (is_myname_or_ipaddr(s)) {
3965                  return WERR_CAN_NOT_COMPLETE;
3966         }
3967
3968         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3969 }
3970
3971 /********************************************************************
3972  * api_spoolss_enumprinters
3973  *
3974  * called from api_spoolss_enumprinters (see this to understand)
3975  ********************************************************************/
3976
3977 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3978                                        struct auth_serversupplied_info *server_info,
3979                                        union spoolss_PrinterInfo **info,
3980                                        uint32_t *count)
3981 {
3982         DEBUG(4,("enum_all_printers_info_2\n"));
3983
3984         return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3985 }
3986
3987 /********************************************************************
3988  * handle enumeration of printers at level 1
3989  ********************************************************************/
3990
3991 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3992                                   struct auth_serversupplied_info *server_info,
3993                                   uint32_t flags,
3994                                   const char *name,
3995                                   union spoolss_PrinterInfo **info,
3996                                   uint32_t *count)
3997 {
3998         /* Not all the flags are equals */
3999
4000         if (flags & PRINTER_ENUM_LOCAL) {
4001                 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
4002         }
4003
4004         if (flags & PRINTER_ENUM_NAME) {
4005                 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
4006         }
4007
4008         if (flags & PRINTER_ENUM_NETWORK) {
4009                 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
4010         }
4011
4012         return WERR_OK; /* NT4sp5 does that */
4013 }
4014
4015 /********************************************************************
4016  * handle enumeration of printers at level 2
4017  ********************************************************************/
4018
4019 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4020                                   struct auth_serversupplied_info *server_info,
4021                                   uint32_t flags,
4022                                   const char *servername,
4023                                   union spoolss_PrinterInfo **info,
4024                                   uint32_t *count)
4025 {
4026         if (flags & PRINTER_ENUM_LOCAL) {
4027                 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4028         }
4029
4030         if (flags & PRINTER_ENUM_NAME) {
4031                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4032                         return WERR_INVALID_NAME;
4033                 }
4034
4035                 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4036         }
4037
4038         if (flags & PRINTER_ENUM_REMOTE) {
4039                 return WERR_UNKNOWN_LEVEL;
4040         }
4041
4042         return WERR_OK;
4043 }
4044
4045 /********************************************************************
4046  * handle enumeration of printers at level 4
4047  ********************************************************************/
4048
4049 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4050                                   struct auth_serversupplied_info *server_info,
4051                                   uint32_t flags,
4052                                   const char *servername,
4053                                   union spoolss_PrinterInfo **info,
4054                                   uint32_t *count)
4055 {
4056         DEBUG(4,("enum_all_printers_info_4\n"));
4057
4058         return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4059 }
4060
4061
4062 /********************************************************************
4063  * handle enumeration of printers at level 5
4064  ********************************************************************/
4065
4066 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4067                                   struct auth_serversupplied_info *server_info,
4068                                   uint32_t flags,
4069                                   const char *servername,
4070                                   union spoolss_PrinterInfo **info,
4071                                   uint32_t *count)
4072 {
4073         DEBUG(4,("enum_all_printers_info_5\n"));
4074
4075         return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4076 }
4077
4078 /****************************************************************
4079  _spoolss_EnumPrinters
4080 ****************************************************************/
4081
4082 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4083                              struct spoolss_EnumPrinters *r)
4084 {
4085         const char *name = NULL;
4086         WERROR result;
4087
4088         /* that's an [in out] buffer */
4089
4090         if (!r->in.buffer && (r->in.offered != 0)) {
4091                 return WERR_INVALID_PARAM;
4092         }
4093
4094         DEBUG(4,("_spoolss_EnumPrinters\n"));
4095
4096         *r->out.needed = 0;
4097         *r->out.count = 0;
4098         *r->out.info = NULL;
4099
4100         /*
4101          * Level 1:
4102          *          flags==PRINTER_ENUM_NAME
4103          *           if name=="" then enumerates all printers
4104          *           if name!="" then enumerate the printer
4105          *          flags==PRINTER_ENUM_REMOTE
4106          *          name is NULL, enumerate printers
4107          * Level 2: name!="" enumerates printers, name can't be NULL
4108          * Level 3: doesn't exist
4109          * Level 4: does a local registry lookup
4110          * Level 5: same as Level 2
4111          */
4112
4113         if (r->in.server) {
4114                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4115                 W_ERROR_HAVE_NO_MEMORY(name);
4116         }
4117
4118         switch (r->in.level) {
4119         case 0:
4120                 result = enumprinters_level0(p->mem_ctx, p->server_info,
4121                                              r->in.flags, name,
4122                                              r->out.info, r->out.count);
4123                 break;
4124         case 1:
4125                 result = enumprinters_level1(p->mem_ctx, p->server_info,
4126                                              r->in.flags, name,
4127                                              r->out.info, r->out.count);
4128                 break;
4129         case 2:
4130                 result = enumprinters_level2(p->mem_ctx, p->server_info,
4131                                              r->in.flags, name,
4132                                              r->out.info, r->out.count);
4133                 break;
4134         case 4:
4135                 result = enumprinters_level4(p->mem_ctx, p->server_info,
4136                                              r->in.flags, name,
4137                                              r->out.info, r->out.count);
4138                 break;
4139         case 5:
4140                 result = enumprinters_level5(p->mem_ctx, p->server_info,
4141                                              r->in.flags, name,
4142                                              r->out.info, r->out.count);
4143                 break;
4144         default:
4145                 return WERR_UNKNOWN_LEVEL;
4146         }
4147
4148         if (!W_ERROR_IS_OK(result)) {
4149                 return result;
4150         }
4151
4152         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4153                                                      spoolss_EnumPrinters, 
4154                                                      *r->out.info, r->in.level,
4155                                                      *r->out.count);
4156         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4157         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4158
4159         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4160 }
4161
4162 /****************************************************************
4163  _spoolss_GetPrinter
4164 ****************************************************************/
4165
4166 WERROR _spoolss_GetPrinter(pipes_struct *p,
4167                            struct spoolss_GetPrinter *r)
4168 {
4169         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4170         struct spoolss_PrinterInfo2 *info2 = NULL;
4171         WERROR result = WERR_OK;
4172         const char *servername = NULL;
4173         int snum;
4174
4175         /* that's an [in out] buffer */
4176
4177         if (!r->in.buffer && (r->in.offered != 0)) {
4178                 return WERR_INVALID_PARAM;
4179         }
4180
4181         *r->out.needed = 0;
4182
4183         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4184                 return WERR_BADFID;
4185         }
4186
4187         if (Printer != NULL || Printer->servername != NULL) {
4188                 servername = Printer->servername;
4189         }
4190
4191         result = winreg_get_printer(p->mem_ctx,
4192                                     p->server_info,
4193                                     servername,
4194                                     lp_const_servicename(snum),
4195                                     &info2);
4196         if (!W_ERROR_IS_OK(result)) {
4197                 return result;
4198         }
4199
4200         switch (r->in.level) {
4201         case 0:
4202                 result = construct_printer_info0(p->mem_ctx, p->server_info,
4203                                                  info2,
4204                                                  &r->out.info->info0, snum);
4205                 break;
4206         case 1:
4207                 result = construct_printer_info1(p->mem_ctx, info2,
4208                                                  PRINTER_ENUM_ICON8,
4209                                                  &r->out.info->info1, snum);
4210                 break;
4211         case 2:
4212                 result = construct_printer_info2(p->mem_ctx, info2,
4213                                                  &r->out.info->info2, snum);
4214                 break;
4215         case 3:
4216                 result = construct_printer_info3(p->mem_ctx, info2,
4217                                                  &r->out.info->info3, snum);
4218                 break;
4219         case 4:
4220                 result = construct_printer_info4(p->mem_ctx, info2,
4221                                                  &r->out.info->info4, snum);
4222                 break;
4223         case 5:
4224                 result = construct_printer_info5(p->mem_ctx, info2,
4225                                                  &r->out.info->info5, snum);
4226                 break;
4227         case 6:
4228                 result = construct_printer_info6(p->mem_ctx, info2,
4229                                                  &r->out.info->info6, snum);
4230                 break;
4231         case 7:
4232                 result = construct_printer_info7(p->mem_ctx, Printer,
4233                                                  &r->out.info->info7, snum);
4234                 break;
4235         case 8:
4236                 result = construct_printer_info8(p->mem_ctx, info2,
4237                                                  &r->out.info->info8, snum);
4238                 break;
4239         default:
4240                 result = WERR_UNKNOWN_LEVEL;
4241                 break;
4242         }
4243
4244         if (!W_ERROR_IS_OK(result)) {
4245                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4246                           r->in.level, win_errstr(result)));
4247                 TALLOC_FREE(r->out.info);
4248                 return result;
4249         }
4250
4251         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4252                                                r->out.info, r->in.level);
4253         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4254
4255         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4256 }
4257
4258 /********************************************************************
4259  ********************************************************************/
4260
4261 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4262         do { \
4263                 if (in && strlen(in)) { \
4264                         out = talloc_strdup(mem_ctx, in); \
4265                         W_ERROR_HAVE_NO_MEMORY(out); \
4266                 } else { \
4267                         out = NULL; \
4268                 } \
4269         } while (0);
4270
4271 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4272         do { \
4273                 if (in && strlen(in)) { \
4274                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4275                 } else { \
4276                         out = talloc_strdup(mem_ctx, ""); \
4277                 } \
4278                 W_ERROR_HAVE_NO_MEMORY(out); \
4279         } while (0);
4280
4281 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4282                                                   const char **string_array,
4283                                                   const char ***presult,
4284                                                   const char *cservername,
4285                                                   const char *arch,
4286                                                   int version)
4287 {
4288         int i, num_strings = 0;
4289         const char **array = NULL;
4290
4291         if (string_array == NULL) {
4292                 return WERR_INVALID_PARAMETER;;
4293         }
4294
4295         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4296                 const char *str = NULL;
4297
4298                 if (cservername == NULL || arch == NULL) {
4299                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4300                 } else {
4301                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4302                 }
4303
4304                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4305                         TALLOC_FREE(array);
4306                         return WERR_NOMEM;
4307                 }
4308         }
4309
4310         if (i > 0) {
4311                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4312                              &array, &num_strings);
4313         }
4314
4315         if (presult) {
4316                 *presult = array;
4317         }
4318
4319         return WERR_OK;
4320 }
4321
4322 /********************************************************************
4323  * fill a spoolss_DriverInfo1 struct
4324  ********************************************************************/
4325
4326 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4327                                         struct spoolss_DriverInfo1 *r,
4328                                         const struct spoolss_DriverInfo8 *driver,
4329                                         const char *servername)
4330 {
4331         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4332         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4333
4334         return WERR_OK;
4335 }
4336
4337 /********************************************************************
4338  * fill a spoolss_DriverInfo2 struct
4339  ********************************************************************/
4340
4341 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4342                                         struct spoolss_DriverInfo2 *r,
4343                                         const struct spoolss_DriverInfo8 *driver,
4344                                         const char *servername)
4345
4346 {
4347         const char *cservername = canon_servername(servername);
4348
4349         r->version              = driver->version;
4350
4351         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4352         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4353         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4354         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4355
4356         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4357                                driver->architecture,
4358                                driver->version,
4359                                driver->driver_path,
4360                                r->driver_path);
4361
4362         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4363                                driver->architecture,
4364                                driver->version,
4365                                driver->data_file,
4366                                r->data_file);
4367
4368         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4369                                driver->architecture,
4370                                driver->version,
4371                                driver->config_file,
4372                                r->config_file);
4373
4374         return WERR_OK;
4375 }
4376
4377 /********************************************************************
4378  * fill a spoolss_DriverInfo3 struct
4379  ********************************************************************/
4380
4381 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4382                                         struct spoolss_DriverInfo3 *r,
4383                                         const struct spoolss_DriverInfo8 *driver,
4384                                         const char *servername)
4385 {
4386         const char *cservername = canon_servername(servername);
4387
4388         r->version              = driver->version;
4389
4390         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4391         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4392         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4393         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4394
4395         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4396                                driver->architecture,
4397                                driver->version,
4398                                driver->driver_path,
4399                                r->driver_path);
4400
4401         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4402                                driver->architecture,
4403                                driver->version,
4404                                driver->data_file,
4405                                r->data_file);
4406
4407         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4408                                driver->architecture,
4409                                driver->version,
4410                                driver->config_file,
4411                                r->config_file);
4412
4413         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4414                                driver->architecture,
4415                                driver->version,
4416                                driver->help_file,
4417                                r->help_file);
4418
4419         FILL_DRIVER_STRING(mem_ctx,
4420                            driver->monitor_name,
4421                            r->monitor_name);
4422
4423         FILL_DRIVER_STRING(mem_ctx,
4424                            driver->default_datatype,
4425                            r->default_datatype);
4426
4427         return string_array_from_driver_info(mem_ctx,
4428                                              driver->dependent_files,
4429                                              &r->dependent_files,
4430                                              cservername,
4431                                              driver->architecture,
4432                                              driver->version);
4433 }
4434
4435 /********************************************************************
4436  * fill a spoolss_DriverInfo4 struct
4437  ********************************************************************/
4438
4439 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4440                                         struct spoolss_DriverInfo4 *r,
4441                                         const struct spoolss_DriverInfo8 *driver,
4442                                         const char *servername)
4443 {
4444         const char *cservername = canon_servername(servername);
4445         WERROR result;
4446
4447         r->version              = driver->version;
4448
4449         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4450         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4451         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4452         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4453
4454         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4455                                driver->architecture,
4456                                driver->version,
4457                                driver->driver_path,
4458                                r->driver_path);
4459
4460         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4461                                driver->architecture,
4462                                driver->version,
4463                                driver->data_file,
4464                                r->data_file);
4465
4466         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4467                                driver->architecture,
4468                                driver->version,
4469                                driver->config_file,
4470                                r->config_file);
4471
4472         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4473                                driver->architecture,
4474                                driver->version,
4475                                driver->help_file,
4476                                r->help_file);
4477
4478         result = string_array_from_driver_info(mem_ctx,
4479                                                driver->dependent_files,
4480                                                &r->dependent_files,
4481                                                cservername,
4482                                                driver->architecture,
4483                                                driver->version);
4484         if (!W_ERROR_IS_OK(result)) {
4485                 return result;
4486         }
4487
4488         FILL_DRIVER_STRING(mem_ctx,
4489                            driver->monitor_name,
4490                            r->monitor_name);
4491
4492         FILL_DRIVER_STRING(mem_ctx,
4493                            driver->default_datatype,
4494                            r->default_datatype);
4495
4496
4497         result = string_array_from_driver_info(mem_ctx,
4498                                                driver->previous_names,
4499                                                &r->previous_names,
4500                                                NULL, NULL, 0);
4501
4502         return result;
4503 }
4504
4505 /********************************************************************
4506  * fill a spoolss_DriverInfo5 struct
4507  ********************************************************************/
4508
4509 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4510                                         struct spoolss_DriverInfo5 *r,
4511                                         const struct spoolss_DriverInfo8 *driver,
4512                                         const char *servername)
4513 {
4514         const char *cservername = canon_servername(servername);
4515
4516         r->version              = driver->version;
4517
4518         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4519         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4520         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4521         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4522
4523         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4524                                driver->architecture,
4525                                driver->version,
4526                                driver->driver_path,
4527                                r->driver_path);
4528
4529         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4530                                driver->architecture,
4531                                driver->version,
4532                                driver->data_file,
4533                                r->data_file);
4534
4535         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536                                driver->architecture,
4537                                driver->version,
4538                                driver->config_file,
4539                                r->config_file);
4540
4541         r->driver_attributes    = 0;
4542         r->config_version       = 0;
4543         r->driver_version       = 0;
4544
4545         return WERR_OK;
4546 }
4547 /********************************************************************
4548  * fill a spoolss_DriverInfo6 struct
4549  ********************************************************************/
4550
4551 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4552                                         struct spoolss_DriverInfo6 *r,
4553                                         const struct spoolss_DriverInfo8 *driver,
4554                                         const char *servername)
4555 {
4556         const char *cservername = canon_servername(servername);
4557         WERROR result;
4558
4559         r->version              = driver->version;
4560
4561         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4562         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4563         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4564         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4565
4566         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4567                                driver->architecture,
4568                                driver->version,
4569                                driver->driver_path,
4570                                r->driver_path);
4571
4572         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573                                driver->architecture,
4574                                driver->version,
4575                                driver->data_file,
4576                                r->data_file);
4577
4578         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4579                                driver->architecture,
4580                                driver->version,
4581                                driver->config_file,
4582                                r->config_file);
4583
4584         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4585                                driver->architecture,
4586                                driver->version,
4587                                driver->help_file,
4588                                r->help_file);
4589
4590         FILL_DRIVER_STRING(mem_ctx,
4591                            driver->monitor_name,
4592                            r->monitor_name);
4593
4594         FILL_DRIVER_STRING(mem_ctx,
4595                            driver->default_datatype,
4596                            r->default_datatype);
4597
4598         result = string_array_from_driver_info(mem_ctx,
4599                                                driver->dependent_files,
4600                                                &r->dependent_files,
4601                                                cservername,
4602                                                driver->architecture,
4603                                                driver->version);
4604         if (!W_ERROR_IS_OK(result)) {
4605                 return result;
4606         }
4607
4608         result = string_array_from_driver_info(mem_ctx,
4609                                                driver->previous_names,
4610                                                &r->previous_names,
4611                                                NULL, NULL, 0);
4612         if (!W_ERROR_IS_OK(result)) {
4613                 return result;
4614         }
4615
4616         r->driver_date          = driver->driver_date;
4617         r->driver_version       = driver->driver_version;
4618
4619         FILL_DRIVER_STRING(mem_ctx,
4620                            driver->manufacturer_name,
4621                            r->manufacturer_name);
4622         FILL_DRIVER_STRING(mem_ctx,
4623                            driver->manufacturer_url,
4624                            r->manufacturer_url);
4625         FILL_DRIVER_STRING(mem_ctx,
4626                            driver->hardware_id,
4627                            r->hardware_id);
4628         FILL_DRIVER_STRING(mem_ctx,
4629                            driver->provider,
4630                            r->provider);
4631
4632         return WERR_OK;
4633 }
4634
4635 /********************************************************************
4636  * fill a spoolss_DriverInfo8 struct
4637  ********************************************************************/
4638
4639 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4640                                         struct spoolss_DriverInfo8 *r,
4641                                         const struct spoolss_DriverInfo8 *driver,
4642                                         const char *servername)
4643 {
4644         const char *cservername = canon_servername(servername);
4645         WERROR result;
4646
4647         r->version              = driver->version;
4648
4649         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4650         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4651         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4652         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4653
4654         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4655                                driver->architecture,
4656                                driver->version,
4657                                driver->driver_path,
4658                                r->driver_path);
4659
4660         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4661                                driver->architecture,
4662                                driver->version,
4663                                driver->data_file,
4664                                r->data_file);
4665
4666         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4667                                driver->architecture,
4668                                driver->version,
4669                                driver->config_file,
4670                                r->config_file);
4671
4672         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4673                                driver->architecture,
4674                                driver->version,
4675                                driver->help_file,
4676                                r->help_file);
4677
4678         FILL_DRIVER_STRING(mem_ctx,
4679                            driver->monitor_name,
4680                            r->monitor_name);
4681
4682         FILL_DRIVER_STRING(mem_ctx,
4683                            driver->default_datatype,
4684                            r->default_datatype);
4685
4686         result = string_array_from_driver_info(mem_ctx,
4687                                                driver->dependent_files,
4688                                                &r->dependent_files,
4689                                                cservername,
4690                                                driver->architecture,
4691                                                driver->version);
4692         if (!W_ERROR_IS_OK(result)) {
4693                 return result;
4694         }
4695
4696         result = string_array_from_driver_info(mem_ctx,
4697                                                driver->previous_names,
4698                                                &r->previous_names,
4699                                                NULL, NULL, 0);
4700         if (!W_ERROR_IS_OK(result)) {
4701                 return result;
4702         }
4703
4704         r->driver_date          = driver->driver_date;
4705         r->driver_version       = driver->driver_version;
4706
4707         FILL_DRIVER_STRING(mem_ctx,
4708                            driver->manufacturer_name,
4709                            r->manufacturer_name);
4710         FILL_DRIVER_STRING(mem_ctx,
4711                            driver->manufacturer_url,
4712                            r->manufacturer_url);
4713         FILL_DRIVER_STRING(mem_ctx,
4714                            driver->hardware_id,
4715                            r->hardware_id);
4716         FILL_DRIVER_STRING(mem_ctx,
4717                            driver->provider,
4718                            r->provider);
4719
4720         FILL_DRIVER_STRING(mem_ctx,
4721                            driver->print_processor,
4722                            r->print_processor);
4723         FILL_DRIVER_STRING(mem_ctx,
4724                            driver->vendor_setup,
4725                            r->vendor_setup);
4726
4727         result = string_array_from_driver_info(mem_ctx,
4728                                                driver->color_profiles,
4729                                                &r->color_profiles,
4730                                                NULL, NULL, 0);
4731         if (!W_ERROR_IS_OK(result)) {
4732                 return result;
4733         }
4734
4735         FILL_DRIVER_STRING(mem_ctx,
4736                            driver->inf_path,
4737                            r->inf_path);
4738
4739         r->printer_driver_attributes    = driver->printer_driver_attributes;
4740
4741         result = string_array_from_driver_info(mem_ctx,
4742                                                driver->core_driver_dependencies,
4743                                                &r->core_driver_dependencies,
4744                                                NULL, NULL, 0);
4745         if (!W_ERROR_IS_OK(result)) {
4746                 return result;
4747         }
4748
4749         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4750         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4751
4752         return WERR_OK;
4753 }
4754
4755 #if 0 /* disabled until marshalling issues are resolved - gd */
4756 /********************************************************************
4757  ********************************************************************/
4758
4759 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4760                                           struct spoolss_DriverFileInfo *r,
4761                                           const char *cservername,
4762                                           const char *file_name,
4763                                           enum spoolss_DriverFileType file_type,
4764                                           uint32_t file_version)
4765 {
4766         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4767                                           cservername, file_name);
4768         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4769         r->file_type    = file_type;
4770         r->file_version = file_version;
4771
4772         return WERR_OK;
4773 }
4774
4775 /********************************************************************
4776  ********************************************************************/
4777
4778 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4779                                                  const struct spoolss_DriverInfo8 *driver,
4780                                                  const char *cservername,
4781                                                  struct spoolss_DriverFileInfo **info_p,
4782                                                  uint32_t *count_p)
4783 {
4784         struct spoolss_DriverFileInfo *info = NULL;
4785         uint32_t count = 0;
4786         WERROR result;
4787         uint32_t i;
4788
4789         *info_p = NULL;
4790         *count_p = 0;
4791
4792         if (strlen(driver->driver_path)) {
4793                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4794                                             struct spoolss_DriverFileInfo,
4795                                             count + 1);
4796                 W_ERROR_HAVE_NO_MEMORY(info);
4797                 result = fill_spoolss_DriverFileInfo(info,
4798                                                      &info[count],
4799                                                      cservername,
4800                                                      driver->driver_path,
4801                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4802                                                      0);
4803                 W_ERROR_NOT_OK_RETURN(result);
4804                 count++;
4805         }
4806
4807         if (strlen(driver->config_file)) {
4808                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4809                                             struct spoolss_DriverFileInfo,
4810                                             count + 1);
4811                 W_ERROR_HAVE_NO_MEMORY(info);
4812                 result = fill_spoolss_DriverFileInfo(info,
4813                                                      &info[count],
4814                                                      cservername,
4815                                                      driver->config_file,
4816                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4817                                                      0);
4818                 W_ERROR_NOT_OK_RETURN(result);
4819                 count++;
4820         }
4821
4822         if (strlen(driver->data_file)) {
4823                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4824                                             struct spoolss_DriverFileInfo,
4825                                             count + 1);
4826                 W_ERROR_HAVE_NO_MEMORY(info);
4827                 result = fill_spoolss_DriverFileInfo(info,
4828                                                      &info[count],
4829                                                      cservername,
4830                                                      driver->data_file,
4831                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4832                                                      0);
4833                 W_ERROR_NOT_OK_RETURN(result);
4834                 count++;
4835         }
4836
4837         if (strlen(driver->help_file)) {
4838                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4839                                             struct spoolss_DriverFileInfo,
4840                                             count + 1);
4841                 W_ERROR_HAVE_NO_MEMORY(info);
4842                 result = fill_spoolss_DriverFileInfo(info,
4843                                                      &info[count],
4844                                                      cservername,
4845                                                      driver->help_file,
4846                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4847                                                      0);
4848                 W_ERROR_NOT_OK_RETURN(result);
4849                 count++;
4850         }
4851
4852         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4853                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4854                                             struct spoolss_DriverFileInfo,
4855                                             count + 1);
4856                 W_ERROR_HAVE_NO_MEMORY(info);
4857                 result = fill_spoolss_DriverFileInfo(info,
4858                                                      &info[count],
4859                                                      cservername,
4860                                                      driver->dependent_files[i],
4861                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4862                                                      0);
4863                 W_ERROR_NOT_OK_RETURN(result);
4864                 count++;
4865         }
4866
4867         *info_p = info;
4868         *count_p = count;
4869
4870         return WERR_OK;
4871 }
4872
4873 /********************************************************************
4874  * fill a spoolss_DriverInfo101 struct
4875  ********************************************************************/
4876
4877 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4878                                           struct spoolss_DriverInfo101 *r,
4879                                           const struct spoolss_DriverInfo8 *driver,
4880                                           const char *servername)
4881 {
4882         const char *cservername = canon_servername(servername);
4883         WERROR result;
4884
4885         r->version              = driver->version;
4886
4887         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4888         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4889         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4890         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4891
4892         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4893                                                     cservername,
4894                                                     &r->file_info,
4895                                                     &r->file_count);
4896         if (!W_ERROR_IS_OK(result)) {
4897                 return result;
4898         }
4899
4900         FILL_DRIVER_STRING(mem_ctx,
4901                            driver->monitor_name,
4902                            r->monitor_name);
4903
4904         FILL_DRIVER_STRING(mem_ctx,
4905                            driver->default_datatype,
4906                            r->default_datatype);
4907
4908         result = string_array_from_driver_info(mem_ctx,
4909                                                driver->previous_names,
4910                                                &r->previous_names,
4911                                                NULL, NULL, 0);
4912         if (!W_ERROR_IS_OK(result)) {
4913                 return result;
4914         }
4915
4916         r->driver_date          = driver->driver_date;
4917         r->driver_version       = driver->driver_version;
4918
4919         FILL_DRIVER_STRING(mem_ctx,
4920                            driver->manufacturer_name,
4921                            r->manufacturer_name);
4922         FILL_DRIVER_STRING(mem_ctx,
4923                            driver->manufacturer_url,
4924                            r->manufacturer_url);
4925         FILL_DRIVER_STRING(mem_ctx,
4926                            driver->hardware_id,
4927                            r->hardware_id);
4928         FILL_DRIVER_STRING(mem_ctx,
4929                            driver->provider,
4930                            r->provider);
4931
4932         return WERR_OK;
4933 }
4934 #endif
4935 /********************************************************************
4936  ********************************************************************/
4937
4938 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4939                                                   struct auth_serversupplied_info *server_info,
4940                                                   uint32_t level,
4941                                                   union spoolss_DriverInfo *r,
4942                                                   int snum,
4943                                                   const char *servername,
4944                                                   const char *architecture,
4945                                                   uint32_t version)
4946 {
4947         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4948         struct spoolss_DriverInfo8 *driver;
4949         WERROR result;
4950
4951         result = winreg_get_printer(mem_ctx,
4952                                     server_info,
4953                                     servername,
4954                                     lp_const_servicename(snum),
4955                                     &pinfo2);
4956
4957         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4958                 win_errstr(result)));
4959
4960         if (!W_ERROR_IS_OK(result)) {
4961                 return WERR_INVALID_PRINTER_NAME;
4962         }
4963
4964         result = winreg_get_driver(mem_ctx, server_info, architecture,
4965                                    pinfo2->drivername, version, &driver);
4966
4967         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4968                 win_errstr(result)));
4969
4970         if (!W_ERROR_IS_OK(result)) {
4971                 /*
4972                  * Is this a W2k client ?
4973                  */
4974
4975                 if (version < 3) {
4976                         talloc_free(pinfo2);
4977                         return WERR_UNKNOWN_PRINTER_DRIVER;
4978                 }
4979
4980                 /* Yes - try again with a WinNT driver. */
4981                 version = 2;
4982                 result = winreg_get_driver(mem_ctx, server_info, architecture,
4983                                            pinfo2->drivername,
4984                                            version, &driver);
4985                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4986                         win_errstr(result)));
4987                 if (!W_ERROR_IS_OK(result)) {
4988                         talloc_free(pinfo2);
4989                         return WERR_UNKNOWN_PRINTER_DRIVER;
4990                 }
4991         }
4992
4993         switch (level) {
4994         case 1:
4995                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4996                 break;
4997         case 2:
4998                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4999                 break;
5000         case 3:
5001                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5002                 break;
5003         case 4:
5004                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5005                 break;
5006         case 5:
5007                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5008                 break;
5009         case 6:
5010                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5011                 break;
5012         case 8:
5013                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5014                 break;
5015 #if 0 /* disabled until marshalling issues are resolved - gd */
5016         case 101:
5017                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5018                 break;
5019 #endif
5020         default:
5021                 result = WERR_UNKNOWN_LEVEL;
5022                 break;
5023         }
5024
5025         talloc_free(pinfo2);
5026         talloc_free(driver);
5027
5028         return result;
5029 }
5030
5031 /****************************************************************
5032  _spoolss_GetPrinterDriver2
5033 ****************************************************************/
5034
5035 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5036                                   struct spoolss_GetPrinterDriver2 *r)
5037 {
5038         Printer_entry *printer;
5039         WERROR result;
5040
5041         int snum;
5042
5043         /* that's an [in out] buffer */
5044
5045         if (!r->in.buffer && (r->in.offered != 0)) {
5046                 return WERR_INVALID_PARAM;
5047         }
5048
5049         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5050
5051         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5052                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5053                 return WERR_INVALID_PRINTER_NAME;
5054         }
5055
5056         *r->out.needed = 0;
5057         *r->out.server_major_version = 0;
5058         *r->out.server_minor_version = 0;
5059
5060         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5061                 return WERR_BADFID;
5062         }
5063
5064         result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
5065                                                      r->in.level, r->out.info,
5066                                                      snum, printer->servername,
5067                                                      r->in.architecture,
5068                                                      r->in.client_major_version);
5069         if (!W_ERROR_IS_OK(result)) {
5070                 TALLOC_FREE(r->out.info);
5071                 return result;
5072         }
5073
5074         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5075                                                r->out.info, r->in.level);
5076         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5077
5078         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5079 }
5080
5081
5082 /****************************************************************
5083  _spoolss_StartPagePrinter
5084 ****************************************************************/
5085
5086 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5087                                  struct spoolss_StartPagePrinter *r)
5088 {
5089         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5090
5091         if (!Printer) {
5092                 DEBUG(3,("_spoolss_StartPagePrinter: "
5093                         "Error in startpageprinter printer handle\n"));
5094                 return WERR_BADFID;
5095         }
5096
5097         Printer->page_started = true;
5098         return WERR_OK;
5099 }
5100
5101 /****************************************************************
5102  _spoolss_EndPagePrinter
5103 ****************************************************************/
5104
5105 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5106                                struct spoolss_EndPagePrinter *r)
5107 {
5108         int snum;
5109
5110         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5111
5112         if (!Printer) {
5113                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5114                         OUR_HANDLE(r->in.handle)));
5115                 return WERR_BADFID;
5116         }
5117
5118         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5119                 return WERR_BADFID;
5120
5121         Printer->page_started = false;
5122         print_job_endpage(snum, Printer->jobid);
5123
5124         return WERR_OK;
5125 }
5126
5127 /****************************************************************
5128  _spoolss_StartDocPrinter
5129 ****************************************************************/
5130
5131 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5132                                 struct spoolss_StartDocPrinter *r)
5133 {
5134         struct spoolss_DocumentInfo1 *info_1;
5135         int snum;
5136         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5137
5138         if (!Printer) {
5139                 DEBUG(2,("_spoolss_StartDocPrinter: "
5140                         "Invalid handle (%s:%u:%u)\n",
5141                         OUR_HANDLE(r->in.handle)));
5142                 return WERR_BADFID;
5143         }
5144
5145         if (r->in.level != 1) {
5146                 return WERR_UNKNOWN_LEVEL;
5147         }
5148
5149         info_1 = r->in.info.info1;
5150
5151         /*
5152          * a nice thing with NT is it doesn't listen to what you tell it.
5153          * when asked to send _only_ RAW datas, it tries to send datas
5154          * in EMF format.
5155          *
5156          * So I add checks like in NT Server ...
5157          */
5158
5159         if (info_1->datatype) {
5160                 if (strcmp(info_1->datatype, "RAW") != 0) {
5161                         *r->out.job_id = 0;
5162                         return WERR_INVALID_DATATYPE;
5163                 }
5164         }
5165
5166         /* get the share number of the printer */
5167         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5168                 return WERR_BADFID;
5169         }
5170
5171         Printer->jobid = print_job_start(p->server_info, snum,
5172                                          info_1->document_name,
5173                                          Printer->devmode);
5174
5175         /* An error occured in print_job_start() so return an appropriate
5176            NT error code. */
5177
5178         if (Printer->jobid == -1) {
5179                 return map_werror_from_unix(errno);
5180         }
5181
5182         Printer->document_started = true;
5183         *r->out.job_id = Printer->jobid;
5184
5185         return WERR_OK;
5186 }
5187
5188 /****************************************************************
5189  _spoolss_EndDocPrinter
5190 ****************************************************************/
5191
5192 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5193                               struct spoolss_EndDocPrinter *r)
5194 {
5195         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5196         int snum;
5197
5198         if (!Printer) {
5199                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5200                         OUR_HANDLE(r->in.handle)));
5201                 return WERR_BADFID;
5202         }
5203
5204         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5205                 return WERR_BADFID;
5206         }
5207
5208         Printer->document_started = false;
5209         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5210         /* error codes unhandled so far ... */
5211
5212         return WERR_OK;
5213 }
5214
5215 /****************************************************************
5216  _spoolss_WritePrinter
5217 ****************************************************************/
5218
5219 WERROR _spoolss_WritePrinter(pipes_struct *p,
5220                              struct spoolss_WritePrinter *r)
5221 {
5222         ssize_t buffer_written;
5223         int snum;
5224         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5225
5226         if (!Printer) {
5227                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5228                         OUR_HANDLE(r->in.handle)));
5229                 *r->out.num_written = r->in._data_size;
5230                 return WERR_BADFID;
5231         }
5232
5233         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5234                 return WERR_BADFID;
5235
5236         buffer_written = print_job_write(snum, Printer->jobid,
5237                                                    (const char *)r->in.data.data,
5238                                                    (SMB_OFF_T)-1,
5239                                                    (size_t)r->in._data_size);
5240         if (buffer_written == (ssize_t)-1) {
5241                 *r->out.num_written = 0;
5242                 if (errno == ENOSPC)
5243                         return WERR_NO_SPOOL_SPACE;
5244                 else
5245                         return WERR_ACCESS_DENIED;
5246         }
5247
5248         *r->out.num_written = r->in._data_size;
5249
5250         return WERR_OK;
5251 }
5252
5253 /********************************************************************
5254  * api_spoolss_getprinter
5255  * called from the spoolss dispatcher
5256  *
5257  ********************************************************************/
5258
5259 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5260                               pipes_struct *p)
5261 {
5262         int snum;
5263         WERROR errcode = WERR_BADFUNC;
5264         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5265
5266         if (!Printer) {
5267                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5268                         OUR_HANDLE(handle)));
5269                 return WERR_BADFID;
5270         }
5271
5272         if (!get_printer_snum(p, handle, &snum, NULL))
5273                 return WERR_BADFID;
5274
5275         switch (command) {
5276         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5277                 errcode = print_queue_pause(p->server_info, snum);
5278                 break;
5279         case SPOOLSS_PRINTER_CONTROL_RESUME:
5280         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5281                 errcode = print_queue_resume(p->server_info, snum);
5282                 break;
5283         case SPOOLSS_PRINTER_CONTROL_PURGE:
5284                 errcode = print_queue_purge(p->server_info, snum);
5285                 break;
5286         default:
5287                 return WERR_UNKNOWN_LEVEL;
5288         }
5289
5290         return errcode;
5291 }
5292
5293
5294 /****************************************************************
5295  _spoolss_AbortPrinter
5296  * From MSDN: "Deletes printer's spool file if printer is configured
5297  * for spooling"
5298 ****************************************************************/
5299
5300 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5301                              struct spoolss_AbortPrinter *r)
5302 {
5303         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5304         int             snum;
5305         WERROR          errcode = WERR_OK;
5306
5307         if (!Printer) {
5308                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5309                         OUR_HANDLE(r->in.handle)));
5310                 return WERR_BADFID;
5311         }
5312
5313         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5314                 return WERR_BADFID;
5315
5316         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5317
5318         return errcode;
5319 }
5320
5321 /********************************************************************
5322  * called by spoolss_api_setprinter
5323  * when updating a printer description
5324  ********************************************************************/
5325
5326 static WERROR update_printer_sec(struct policy_handle *handle,
5327                                  pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5328 {
5329         struct spoolss_security_descriptor *new_secdesc = NULL;
5330         struct spoolss_security_descriptor *old_secdesc = NULL;
5331         const char *printer;
5332         WERROR result;
5333         int snum;
5334
5335         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5336
5337         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5338                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5339                          OUR_HANDLE(handle)));
5340
5341                 result = WERR_BADFID;
5342                 goto done;
5343         }
5344
5345         if (secdesc_ctr == NULL) {
5346                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5347                 result = WERR_INVALID_PARAM;
5348                 goto done;
5349         }
5350         printer = lp_const_servicename(snum);
5351
5352         /* Check the user has permissions to change the security
5353            descriptor.  By experimentation with two NT machines, the user
5354            requires Full Access to the printer to change security
5355            information. */
5356
5357         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5358                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5359                 result = WERR_ACCESS_DENIED;
5360                 goto done;
5361         }
5362
5363         /* NT seems to like setting the security descriptor even though
5364            nothing may have actually changed. */
5365         result = winreg_get_printer_secdesc(p->mem_ctx,
5366                                             p->server_info,
5367                                             printer,
5368                                             &old_secdesc);
5369         if (!W_ERROR_IS_OK(result)) {
5370                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5371                 result = WERR_BADFID;
5372                 goto done;
5373         }
5374
5375         if (DEBUGLEVEL >= 10) {
5376                 struct security_acl *the_acl;
5377                 int i;
5378
5379                 the_acl = secdesc_ctr->sd->dacl;
5380                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5381                            printer, the_acl->num_aces));
5382
5383                 for (i = 0; i < the_acl->num_aces; i++) {
5384                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5385                                            &the_acl->aces[i].trustee),
5386                                   the_acl->aces[i].access_mask));
5387                 }
5388
5389                 the_acl = secdesc_ctr->sd->dacl;
5390
5391                 if (the_acl) {
5392                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5393                                    printer, the_acl->num_aces));
5394
5395                         for (i = 0; i < the_acl->num_aces; i++) {
5396                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5397                                                    &the_acl->aces[i].trustee),
5398                                            the_acl->aces[i].access_mask));
5399                         }
5400                 } else {
5401                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5402                 }
5403         }
5404
5405         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5406         if (new_secdesc == NULL) {
5407                 result = WERR_NOMEM;
5408                 goto done;
5409         }
5410
5411         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5412                 result = WERR_OK;
5413                 goto done;
5414         }
5415
5416         result = winreg_set_printer_secdesc(p->mem_ctx,
5417                                             p->server_info,
5418                                             printer,
5419                                             new_secdesc);
5420
5421  done:
5422         return result;
5423 }
5424
5425 /********************************************************************
5426  Canonicalize printer info from a client
5427
5428  ATTN: It does not matter what we set the servername to hear
5429  since we do the necessary work in get_a_printer() to set it to
5430  the correct value based on what the client sent in the
5431  _spoolss_open_printer_ex().
5432  ********************************************************************/
5433
5434 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5435                              struct spoolss_SetPrinterInfo2 *info2,
5436                              int snum)
5437 {
5438         fstring printername;
5439         const char *p;
5440
5441         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5442                 "portname=%s drivername=%s comment=%s location=%s\n",
5443                 info2->servername, info2->printername, info2->sharename,
5444                 info2->portname, info2->drivername, info2->comment,
5445                 info2->location));
5446
5447         /* we force some elements to "correct" values */
5448         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5449         if (info2->servername == NULL) {
5450                 return false;
5451         }
5452         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5453         if (info2->sharename == NULL) {
5454                 return false;
5455         }
5456
5457         /* check to see if we allow printername != sharename */
5458         if (lp_force_printername(snum)) {
5459                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5460                                         global_myname(), info2->sharename);
5461         } else {
5462                 /* make sure printername is in \\server\printername format */
5463                 fstrcpy(printername, info2->printername);
5464                 p = printername;
5465                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5466                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5467                                 p++;
5468                 }
5469
5470                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5471                                         global_myname(), p);
5472         }
5473         if (info2->printername == NULL) {
5474                 return false;
5475         }
5476
5477         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5478         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5479
5480         return true;
5481 }
5482
5483 /****************************************************************************
5484 ****************************************************************************/
5485
5486 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5487 {
5488         char *cmd = lp_addport_cmd();
5489         char *command = NULL;
5490         int ret;
5491         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5492         bool is_print_op = false;
5493
5494         if ( !*cmd ) {
5495                 return WERR_ACCESS_DENIED;
5496         }
5497
5498         command = talloc_asprintf(ctx,
5499                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5500         if (!command) {
5501                 return WERR_NOMEM;
5502         }
5503
5504         if ( token )
5505                 is_print_op = user_has_privileges( token, &se_printop );
5506
5507         DEBUG(10,("Running [%s]\n", command));
5508
5509         /********* BEGIN SePrintOperatorPrivilege **********/
5510
5511         if ( is_print_op )
5512                 become_root();
5513
5514         ret = smbrun(command, NULL);
5515
5516         if ( is_print_op )
5517                 unbecome_root();
5518
5519         /********* END SePrintOperatorPrivilege **********/
5520
5521         DEBUGADD(10,("returned [%d]\n", ret));
5522
5523         TALLOC_FREE(command);
5524
5525         if ( ret != 0 ) {
5526                 return WERR_ACCESS_DENIED;
5527         }
5528
5529         return WERR_OK;
5530 }
5531
5532 /****************************************************************************
5533 ****************************************************************************/
5534
5535 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5536                       struct spoolss_SetPrinterInfo2 *info2)
5537 {
5538         char *cmd = lp_addprinter_cmd();
5539         char **qlines;
5540         char *command = NULL;
5541         int numlines;
5542         int ret;
5543         int fd;
5544         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5545         bool is_print_op = false;
5546         char *remote_machine = talloc_strdup(ctx, "%m");
5547
5548         if (!remote_machine) {
5549                 return false;
5550         }
5551         remote_machine = talloc_sub_basic(ctx,
5552                                 current_user_info.smb_name,
5553                                 current_user_info.domain,
5554                                 remote_machine);
5555         if (!remote_machine) {
5556                 return false;
5557         }
5558
5559         command = talloc_asprintf(ctx,
5560                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5561                         cmd, info2->printername, info2->sharename,
5562                         info2->portname, info2->drivername,
5563                         info2->location, info2->comment, remote_machine);
5564         if (!command) {
5565                 return false;
5566         }
5567
5568         if ( token )
5569                 is_print_op = user_has_privileges( token, &se_printop );
5570
5571         DEBUG(10,("Running [%s]\n", command));
5572
5573         /********* BEGIN SePrintOperatorPrivilege **********/
5574
5575         if ( is_print_op )
5576                 become_root();
5577
5578         if ( (ret = smbrun(command, &fd)) == 0 ) {
5579                 /* Tell everyone we updated smb.conf. */
5580                 message_send_all(smbd_messaging_context(),
5581                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5582         }
5583
5584         if ( is_print_op )
5585                 unbecome_root();
5586
5587         /********* END SePrintOperatorPrivilege **********/
5588
5589         DEBUGADD(10,("returned [%d]\n", ret));
5590
5591         TALLOC_FREE(command);
5592         TALLOC_FREE(remote_machine);
5593
5594         if ( ret != 0 ) {
5595                 if (fd != -1)
5596                         close(fd);
5597                 return false;
5598         }
5599
5600         /* reload our services immediately */
5601         become_root();
5602         reload_services(false);
5603         unbecome_root();
5604
5605         numlines = 0;
5606         /* Get lines and convert them back to dos-codepage */
5607         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5608         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5609         close(fd);
5610
5611         /* Set the portname to what the script says the portname should be. */
5612         /* but don't require anything to be return from the script exit a good error code */
5613
5614         if (numlines) {
5615                 /* Set the portname to what the script says the portname should be. */
5616                 info2->portname = talloc_strdup(ctx, qlines[0]);
5617                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5618         }
5619
5620         TALLOC_FREE(qlines);
5621         return true;
5622 }
5623
5624
5625 /********************************************************************
5626  * Called by spoolss_api_setprinter
5627  * when updating a printer description.
5628  ********************************************************************/
5629
5630 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5631                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5632                              struct spoolss_DeviceMode *devmode)
5633 {
5634         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5635         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5636         struct spoolss_PrinterInfo2 *old_printer;
5637         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5638         const char *servername = NULL;
5639         const char *uncname;
5640         int snum;
5641         WERROR result = WERR_OK;
5642         DATA_BLOB buffer;
5643         TALLOC_CTX *tmp_ctx;
5644
5645         DEBUG(8,("update_printer\n"));
5646
5647         tmp_ctx = talloc_new(p->mem_ctx);
5648         if (tmp_ctx == NULL) {
5649                 return WERR_NOMEM;
5650         }
5651
5652         if (!Printer) {
5653                 result = WERR_BADFID;
5654                 goto done;
5655         }
5656
5657         if (!get_printer_snum(p, handle, &snum, NULL)) {
5658                 result = WERR_BADFID;
5659                 goto done;
5660         }
5661
5662         if (Printer != NULL || Printer->servername != NULL) {
5663                 servername = Printer->servername;
5664         }
5665
5666         result = winreg_get_printer(tmp_ctx,
5667                                     p->server_info,
5668                                     servername,
5669                                     lp_const_servicename(snum),
5670                                     &old_printer);
5671         if (!W_ERROR_IS_OK(result)) {
5672                 result = WERR_BADFID;
5673                 goto done;
5674         }
5675
5676         /* Do sanity check on the requested changes for Samba */
5677         if (!check_printer_ok(tmp_ctx, printer, snum)) {
5678                 result = WERR_INVALID_PARAM;
5679                 goto done;
5680         }
5681
5682         /* FIXME!!! If the driver has changed we really should verify that
5683            it is installed before doing much else   --jerry */
5684
5685         /* Check calling user has permission to update printer description */
5686         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5687                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5688                 result = WERR_ACCESS_DENIED;
5689                 goto done;
5690         }
5691
5692         /* Call addprinter hook */
5693         /* Check changes to see if this is really needed */
5694
5695         if (*lp_addprinter_cmd() &&
5696                         (!strequal(printer->drivername, old_printer->drivername) ||
5697                          !strequal(printer->comment, old_printer->comment) ||
5698                          !strequal(printer->portname, old_printer->portname) ||
5699                          !strequal(printer->location, old_printer->location)) )
5700         {
5701                 /* add_printer_hook() will call reload_services() */
5702                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
5703                                       printer) ) {
5704                         result = WERR_ACCESS_DENIED;
5705                         goto done;
5706                 }
5707         }
5708
5709         /*
5710          * When a *new* driver is bound to a printer, the drivername is used to
5711          * lookup previously saved driver initialization info, which is then
5712          * bound to the printer, simulating what happens in the Windows arch.
5713          */
5714         if (!strequal(printer->drivername, old_printer->drivername)) {
5715                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5716                         printer->drivername));
5717
5718                 notify_printer_driver(snum, printer->drivername);
5719         }
5720
5721         /*
5722          * flag which changes actually occured.  This is a small subset of
5723          * all the possible changes.  We also have to update things in the
5724          * DsSpooler key.
5725          */
5726         if (!strequal(printer->comment, old_printer->comment)) {
5727                 push_reg_sz(tmp_ctx, &buffer, printer->comment);
5728                 winreg_set_printer_dataex(p->mem_ctx,
5729                                           p->server_info,
5730                                           printer->sharename,
5731                                           SPOOL_DSSPOOLER_KEY,
5732                                           "description",
5733                                           REG_SZ,
5734                                           buffer.data,
5735                                           buffer.length);
5736
5737                 notify_printer_comment(snum, printer->comment);
5738         }
5739
5740         if (!strequal(printer->sharename, old_printer->sharename)) {
5741                 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
5742                 winreg_set_printer_dataex(tmp_ctx,
5743                                           p->server_info,
5744                                           printer->sharename,
5745                                           SPOOL_DSSPOOLER_KEY,
5746                                           "shareName",
5747                                           REG_SZ,
5748                                           buffer.data,
5749                                           buffer.length);
5750
5751                 notify_printer_sharename(snum, printer->sharename);
5752         }
5753
5754         if (!strequal(printer->printername, old_printer->printername)) {
5755                 const char *pname;
5756
5757                 if ( (pname = strchr_m( printer->printername+2, '\\' )) != NULL )
5758                         pname++;
5759                 else
5760                         pname = printer->printername;
5761
5762                 push_reg_sz(tmp_ctx, &buffer, pname);
5763                 winreg_set_printer_dataex(tmp_ctx,
5764                                           p->server_info,
5765                                           printer->sharename,
5766                                           SPOOL_DSSPOOLER_KEY,
5767                                           "printerName",
5768                                           REG_SZ,
5769                                           buffer.data,
5770                                           buffer.length);
5771
5772                 notify_printer_printername( snum, pname );
5773         }
5774
5775         if (!strequal(printer->portname, old_printer->portname)) {
5776                 push_reg_sz(tmp_ctx, &buffer, printer->portname);
5777                 winreg_set_printer_dataex(tmp_ctx,
5778                                           p->server_info,
5779                                           printer->sharename,
5780                                           SPOOL_DSSPOOLER_KEY,
5781                                           "portName",
5782                                           REG_SZ,
5783                                           buffer.data,
5784                                           buffer.length);
5785
5786                 notify_printer_port(snum, printer->portname);
5787         }
5788
5789         if (!strequal(printer->location, old_printer->location)) {
5790                 push_reg_sz(tmp_ctx, &buffer, printer->location);
5791                 winreg_set_printer_dataex(tmp_ctx,
5792                                           p->server_info,
5793                                           printer->sharename,
5794                                           SPOOL_DSSPOOLER_KEY,
5795                                           "location",
5796                                           REG_SZ,
5797                                           buffer.data,
5798                                           buffer.length);
5799
5800                 notify_printer_location(snum, printer->location);
5801         }
5802
5803         /* here we need to update some more DsSpooler keys */
5804         /* uNCName, serverName, shortServerName */
5805
5806         push_reg_sz(tmp_ctx, &buffer, global_myname());
5807         winreg_set_printer_dataex(tmp_ctx,
5808                                   p->server_info,
5809                                   printer->sharename,
5810                                   SPOOL_DSSPOOLER_KEY,
5811                                   "serverName",
5812                                   REG_SZ,
5813                                   buffer.data,
5814                                   buffer.length);
5815         winreg_set_printer_dataex(tmp_ctx,
5816                                   p->server_info,
5817                                   printer->sharename,
5818                                   SPOOL_DSSPOOLER_KEY,
5819                                   "shortServerName",
5820                                   REG_SZ,
5821                                   buffer.data,
5822                                   buffer.length);
5823
5824         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
5825                                   global_myname(), printer->sharename);
5826         push_reg_sz(tmp_ctx, &buffer, uncname);
5827         winreg_set_printer_dataex(tmp_ctx,
5828                                   p->server_info,
5829                                   printer->sharename,
5830                                   SPOOL_DSSPOOLER_KEY,
5831                                   "uNCName",
5832                                   REG_SZ,
5833                                   buffer.data,
5834                                   buffer.length);
5835
5836         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5837
5838         if (devmode == NULL) {
5839                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5840         }
5841         result = winreg_update_printer(tmp_ctx,
5842                                        p->server_info,
5843                                        printer->sharename,
5844                                        printer_mask,
5845                                        printer,
5846                                        devmode,
5847                                        NULL);
5848
5849 done:
5850         talloc_free(tmp_ctx);
5851
5852         return result;
5853 }
5854
5855 /****************************************************************************
5856 ****************************************************************************/
5857 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5858                                            struct policy_handle *handle,
5859                                            struct spoolss_SetPrinterInfo7 *info7)
5860 {
5861 #ifdef HAVE_ADS
5862         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5863         WERROR result;
5864         int snum;
5865         Printer_entry *Printer;
5866
5867         if ( lp_security() != SEC_ADS ) {
5868                 return WERR_UNKNOWN_LEVEL;
5869         }
5870
5871         Printer = find_printer_index_by_hnd(p, handle);
5872
5873         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5874
5875         if (!Printer)
5876                 return WERR_BADFID;
5877
5878         if (!get_printer_snum(p, handle, &snum, NULL))
5879                 return WERR_BADFID;
5880
5881         result = winreg_get_printer(p->mem_ctx, p->server_info,
5882                                     Printer->servername,
5883                                     lp_servicename(snum), &pinfo2);
5884         if (!W_ERROR_IS_OK(result)) {
5885                 return WERR_BADFID;
5886         }
5887
5888         nt_printer_publish(pinfo2, p->server_info, pinfo2, info7->action);
5889
5890         TALLOC_FREE(pinfo2);
5891         return WERR_OK;
5892 #else
5893         return WERR_UNKNOWN_LEVEL;
5894 #endif
5895 }
5896
5897 /********************************************************************
5898  ********************************************************************/
5899
5900 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5901                                      struct spoolss_DeviceMode *devmode)
5902 {
5903         int snum;
5904         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5905         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
5906
5907         DEBUG(8,("update_printer_devmode\n"));
5908
5909         if (!Printer) {
5910                 return WERR_BADFID;
5911         }
5912
5913         if (!get_printer_snum(p, handle, &snum, NULL)) {
5914                 return WERR_BADFID;
5915         }
5916
5917         /* Check calling user has permission to update printer description */
5918         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5919                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5920                 return WERR_ACCESS_DENIED;
5921         }
5922
5923         return winreg_update_printer(p->mem_ctx,
5924                                      p->server_info,
5925                                      lp_const_servicename(snum),
5926                                      info2_mask,
5927                                      NULL,
5928                                      devmode,
5929                                      NULL);
5930 }
5931
5932
5933 /****************************************************************
5934  _spoolss_SetPrinter
5935 ****************************************************************/
5936
5937 WERROR _spoolss_SetPrinter(pipes_struct *p,
5938                            struct spoolss_SetPrinter *r)
5939 {
5940         WERROR result;
5941
5942         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5943
5944         if (!Printer) {
5945                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5946                         OUR_HANDLE(r->in.handle)));
5947                 return WERR_BADFID;
5948         }
5949
5950         /* check the level */
5951         switch (r->in.info_ctr->level) {
5952                 case 0:
5953                         return control_printer(r->in.handle, r->in.command, p);
5954                 case 2:
5955                         result = update_printer(p, r->in.handle,
5956                                                 r->in.info_ctr,
5957                                                 r->in.devmode_ctr->devmode);
5958                         if (!W_ERROR_IS_OK(result))
5959                                 return result;
5960                         if (r->in.secdesc_ctr->sd)
5961                                 result = update_printer_sec(r->in.handle, p,
5962                                                             r->in.secdesc_ctr);
5963                         return result;
5964                 case 3:
5965                         return update_printer_sec(r->in.handle, p,
5966                                                   r->in.secdesc_ctr);
5967                 case 7:
5968                         return publish_or_unpublish_printer(p, r->in.handle,
5969                                                             r->in.info_ctr->info.info7);
5970                 case 8:
5971                         return update_printer_devmode(p, r->in.handle,
5972                                                       r->in.devmode_ctr->devmode);
5973                 default:
5974                         return WERR_UNKNOWN_LEVEL;
5975         }
5976 }
5977
5978 /****************************************************************
5979  _spoolss_FindClosePrinterNotify
5980 ****************************************************************/
5981
5982 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5983                                        struct spoolss_FindClosePrinterNotify *r)
5984 {
5985         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5986
5987         if (!Printer) {
5988                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5989                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5990                 return WERR_BADFID;
5991         }
5992
5993         if (Printer->notify.client_connected == true) {
5994                 int snum = -1;
5995
5996                 if ( Printer->printer_type == SPLHND_SERVER)
5997                         snum = -1;
5998                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5999                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6000                         return WERR_BADFID;
6001
6002                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6003         }
6004
6005         Printer->notify.flags=0;
6006         Printer->notify.options=0;
6007         Printer->notify.localmachine[0]='\0';
6008         Printer->notify.printerlocal=0;
6009         TALLOC_FREE(Printer->notify.option);
6010         Printer->notify.client_connected = false;
6011
6012         return WERR_OK;
6013 }
6014
6015 /****************************************************************
6016  _spoolss_AddJob
6017 ****************************************************************/
6018
6019 WERROR _spoolss_AddJob(pipes_struct *p,
6020                        struct spoolss_AddJob *r)
6021 {
6022         if (!r->in.buffer && (r->in.offered != 0)) {
6023                 return WERR_INVALID_PARAM;
6024         }
6025
6026         /* this is what a NT server returns for AddJob. AddJob must fail on
6027          * non-local printers */
6028
6029         if (r->in.level != 1) {
6030                 return WERR_UNKNOWN_LEVEL;
6031         }
6032
6033         return WERR_INVALID_PARAM;
6034 }
6035
6036 /****************************************************************************
6037 fill_job_info1
6038 ****************************************************************************/
6039
6040 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6041                              struct spoolss_JobInfo1 *r,
6042                              const print_queue_struct *queue,
6043                              int position, int snum,
6044                              struct spoolss_PrinterInfo2 *pinfo2)
6045 {
6046         struct tm *t;
6047
6048         t = gmtime(&queue->time);
6049
6050         r->job_id               = queue->job;
6051
6052         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6053         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6054         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6055         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6056         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6057         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6058         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6059         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6060         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6061         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6062         r->text_status          = talloc_strdup(mem_ctx, "");
6063         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6064
6065         r->status               = nt_printj_status(queue->status);
6066         r->priority             = queue->priority;
6067         r->position             = position;
6068         r->total_pages          = queue->page_count;
6069         r->pages_printed        = 0; /* ??? */
6070
6071         init_systemtime(&r->submitted, t);
6072
6073         return WERR_OK;
6074 }
6075
6076 /****************************************************************************
6077 fill_job_info2
6078 ****************************************************************************/
6079
6080 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6081                              struct spoolss_JobInfo2 *r,
6082                              const print_queue_struct *queue,
6083                              int position, int snum,
6084                              struct spoolss_PrinterInfo2 *pinfo2,
6085                              struct spoolss_DeviceMode *devmode)
6086 {
6087         struct tm *t;
6088
6089         t = gmtime(&queue->time);
6090
6091         r->job_id               = queue->job;
6092
6093         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6094         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6095         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6096         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6097         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6098         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6099         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6100         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6101         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6102         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6103         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6104         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6105         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6106         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6107         r->parameters           = talloc_strdup(mem_ctx, "");
6108         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6109         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6110         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6111
6112         r->devmode              = devmode;
6113
6114         r->text_status          = talloc_strdup(mem_ctx, "");
6115         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6116
6117         r->secdesc              = NULL;
6118
6119         r->status               = nt_printj_status(queue->status);
6120         r->priority             = queue->priority;
6121         r->position             = position;
6122         r->start_time           = 0;
6123         r->until_time           = 0;
6124         r->total_pages          = queue->page_count;
6125         r->size                 = queue->size;
6126         init_systemtime(&r->submitted, t);
6127         r->time                 = 0;
6128         r->pages_printed        = 0; /* ??? */
6129
6130         return WERR_OK;
6131 }
6132
6133 /****************************************************************************
6134 fill_job_info3
6135 ****************************************************************************/
6136
6137 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6138                              struct spoolss_JobInfo3 *r,
6139                              const print_queue_struct *queue,
6140                              const print_queue_struct *next_queue,
6141                              int position, int snum,
6142                              struct spoolss_PrinterInfo2 *pinfo2)
6143 {
6144         r->job_id               = queue->job;
6145         r->next_job_id          = 0;
6146         if (next_queue) {
6147                 r->next_job_id  = next_queue->job;
6148         }
6149         r->reserved             = 0;
6150
6151         return WERR_OK;
6152 }
6153
6154 /****************************************************************************
6155  Enumjobs at level 1.
6156 ****************************************************************************/
6157
6158 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6159                               const print_queue_struct *queue,
6160                               uint32_t num_queues, int snum,
6161                               struct spoolss_PrinterInfo2 *pinfo2,
6162                               union spoolss_JobInfo **info_p,
6163                               uint32_t *count)
6164 {
6165         union spoolss_JobInfo *info;
6166         int i;
6167         WERROR result = WERR_OK;
6168
6169         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6170         W_ERROR_HAVE_NO_MEMORY(info);
6171
6172         *count = num_queues;
6173
6174         for (i=0; i<*count; i++) {
6175                 result = fill_job_info1(info,
6176                                         &info[i].info1,
6177                                         &queue[i],
6178                                         i,
6179                                         snum,
6180                                         pinfo2);
6181                 if (!W_ERROR_IS_OK(result)) {
6182                         goto out;
6183                 }
6184         }
6185
6186  out:
6187         if (!W_ERROR_IS_OK(result)) {
6188                 TALLOC_FREE(info);
6189                 *count = 0;
6190                 return result;
6191         }
6192
6193         *info_p = info;
6194
6195         return WERR_OK;
6196 }
6197
6198 /****************************************************************************
6199  Enumjobs at level 2.
6200 ****************************************************************************/
6201
6202 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6203                               const print_queue_struct *queue,
6204                               uint32_t num_queues, int snum,
6205                               struct spoolss_PrinterInfo2 *pinfo2,
6206                               union spoolss_JobInfo **info_p,
6207                               uint32_t *count)
6208 {
6209         union spoolss_JobInfo *info;
6210         int i;
6211         WERROR result = WERR_OK;
6212
6213         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6214         W_ERROR_HAVE_NO_MEMORY(info);
6215
6216         *count = num_queues;
6217
6218         for (i=0; i<*count; i++) {
6219                 struct spoolss_DeviceMode *devmode;
6220
6221                 result = spoolss_create_default_devmode(info,
6222                                                         pinfo2->printername,
6223                                                         &devmode);
6224                 if (!W_ERROR_IS_OK(result)) {
6225                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6226                         goto out;
6227                 }
6228
6229                 result = fill_job_info2(info,
6230                                         &info[i].info2,
6231                                         &queue[i],
6232                                         i,
6233                                         snum,
6234                                         pinfo2,
6235                                         devmode);
6236                 if (!W_ERROR_IS_OK(result)) {
6237                         goto out;
6238                 }
6239         }
6240
6241  out:
6242         if (!W_ERROR_IS_OK(result)) {
6243                 TALLOC_FREE(info);
6244                 *count = 0;
6245                 return result;
6246         }
6247
6248         *info_p = info;
6249
6250         return WERR_OK;
6251 }
6252
6253 /****************************************************************************
6254  Enumjobs at level 3.
6255 ****************************************************************************/
6256
6257 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6258                               const print_queue_struct *queue,
6259                               uint32_t num_queues, int snum,
6260                               struct spoolss_PrinterInfo2 *pinfo2,
6261                               union spoolss_JobInfo **info_p,
6262                               uint32_t *count)
6263 {
6264         union spoolss_JobInfo *info;
6265         int i;
6266         WERROR result = WERR_OK;
6267
6268         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6269         W_ERROR_HAVE_NO_MEMORY(info);
6270
6271         *count = num_queues;
6272
6273         for (i=0; i<*count; i++) {
6274                 const print_queue_struct *next_queue = NULL;
6275
6276                 if (i+1 < *count) {
6277                         next_queue = &queue[i+1];
6278                 }
6279
6280                 result = fill_job_info3(info,
6281                                         &info[i].info3,
6282                                         &queue[i],
6283                                         next_queue,
6284                                         i,
6285                                         snum,
6286                                         pinfo2);
6287                 if (!W_ERROR_IS_OK(result)) {
6288                         goto out;
6289                 }
6290         }
6291
6292  out:
6293         if (!W_ERROR_IS_OK(result)) {
6294                 TALLOC_FREE(info);
6295                 *count = 0;
6296                 return result;
6297         }
6298
6299         *info_p = info;
6300
6301         return WERR_OK;
6302 }
6303
6304 /****************************************************************
6305  _spoolss_EnumJobs
6306 ****************************************************************/
6307
6308 WERROR _spoolss_EnumJobs(pipes_struct *p,
6309                          struct spoolss_EnumJobs *r)
6310 {
6311         WERROR result;
6312         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6313         int snum;
6314         print_status_struct prt_status;
6315         print_queue_struct *queue = NULL;
6316         uint32_t count;
6317
6318         /* that's an [in out] buffer */
6319
6320         if (!r->in.buffer && (r->in.offered != 0)) {
6321                 return WERR_INVALID_PARAM;
6322         }
6323
6324         DEBUG(4,("_spoolss_EnumJobs\n"));
6325
6326         *r->out.needed = 0;
6327         *r->out.count = 0;
6328         *r->out.info = NULL;
6329
6330         /* lookup the printer snum and tdb entry */
6331
6332         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6333                 return WERR_BADFID;
6334         }
6335
6336         result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
6337                                     lp_servicename(snum), &pinfo2);
6338         if (!W_ERROR_IS_OK(result)) {
6339                 return result;
6340         }
6341
6342         count = print_queue_status(snum, &queue, &prt_status);
6343         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6344                 count, prt_status.status, prt_status.message));
6345
6346         if (count == 0) {
6347                 SAFE_FREE(queue);
6348                 TALLOC_FREE(pinfo2);
6349                 return WERR_OK;
6350         }
6351
6352         switch (r->in.level) {
6353         case 1:
6354                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6355                                          pinfo2, r->out.info, r->out.count);
6356                 break;
6357         case 2:
6358                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6359                                          pinfo2, r->out.info, r->out.count);
6360                 break;
6361         case 3:
6362                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6363                                          pinfo2, r->out.info, r->out.count);
6364                 break;
6365         default:
6366                 result = WERR_UNKNOWN_LEVEL;
6367                 break;
6368         }
6369
6370         SAFE_FREE(queue);
6371         TALLOC_FREE(pinfo2);
6372
6373         if (!W_ERROR_IS_OK(result)) {
6374                 return result;
6375         }
6376
6377         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6378                                                      spoolss_EnumJobs, 
6379                                                      *r->out.info, r->in.level,
6380                                                      *r->out.count);
6381         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6382         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6383
6384         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6385 }
6386
6387 /****************************************************************
6388  _spoolss_ScheduleJob
6389 ****************************************************************/
6390
6391 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6392                             struct spoolss_ScheduleJob *r)
6393 {
6394         return WERR_OK;
6395 }
6396
6397 /****************************************************************
6398 ****************************************************************/
6399
6400 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6401                                const char *printer_name,
6402                                uint32_t job_id,
6403                                struct spoolss_SetJobInfo1 *r)
6404 {
6405         char *old_doc_name;
6406
6407         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6408                 return WERR_BADFID;
6409         }
6410
6411         if (strequal(old_doc_name, r->document_name)) {
6412                 return WERR_OK;
6413         }
6414
6415         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6416                 return WERR_BADFID;
6417         }
6418
6419         return WERR_OK;
6420 }
6421
6422 /****************************************************************
6423  _spoolss_SetJob
6424 ****************************************************************/
6425
6426 WERROR _spoolss_SetJob(pipes_struct *p,
6427                        struct spoolss_SetJob *r)
6428 {
6429         int snum;
6430         WERROR errcode = WERR_BADFUNC;
6431
6432         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6433                 return WERR_BADFID;
6434         }
6435
6436         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6437                 return WERR_INVALID_PRINTER_NAME;
6438         }
6439
6440         switch (r->in.command) {
6441         case SPOOLSS_JOB_CONTROL_CANCEL:
6442         case SPOOLSS_JOB_CONTROL_DELETE:
6443                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6444                         errcode = WERR_OK;
6445                 }
6446                 break;
6447         case SPOOLSS_JOB_CONTROL_PAUSE:
6448                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6449                         errcode = WERR_OK;
6450                 }
6451                 break;
6452         case SPOOLSS_JOB_CONTROL_RESTART:
6453         case SPOOLSS_JOB_CONTROL_RESUME:
6454                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6455                         errcode = WERR_OK;
6456                 }
6457                 break;
6458         case 0:
6459                 errcode = WERR_OK;
6460                 break;
6461         default:
6462                 return WERR_UNKNOWN_LEVEL;
6463         }
6464
6465         if (!W_ERROR_IS_OK(errcode)) {
6466                 return errcode;
6467         }
6468
6469         if (r->in.ctr == NULL) {
6470                 return errcode;
6471         }
6472
6473         switch (r->in.ctr->level) {
6474         case 1:
6475                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6476                                            r->in.job_id,
6477                                            r->in.ctr->info.info1);
6478                 break;
6479         case 2:
6480         case 3:
6481         case 4:
6482         default:
6483                 return WERR_UNKNOWN_LEVEL;
6484         }
6485
6486         return errcode;
6487 }
6488
6489 /****************************************************************************
6490  Enumerates all printer drivers by level and architecture.
6491 ****************************************************************************/
6492
6493 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6494                                                        struct auth_serversupplied_info *server_info,
6495                                                        const char *servername,
6496                                                        const char *architecture,
6497                                                        uint32_t level,
6498                                                        union spoolss_DriverInfo **info_p,
6499                                                        uint32_t *count_p)
6500 {
6501         int i;
6502         uint32_t version;
6503         struct spoolss_DriverInfo8 *driver;
6504         union spoolss_DriverInfo *info = NULL;
6505         uint32_t count = 0;
6506         WERROR result = WERR_OK;
6507         uint32_t num_drivers;
6508         const char **drivers;
6509
6510         *count_p = 0;
6511         *info_p = NULL;
6512
6513         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6514                 result = winreg_get_driver_list(mem_ctx, server_info,
6515                                                 architecture, version,
6516                                                 &num_drivers, &drivers);
6517                 if (!W_ERROR_IS_OK(result)) {
6518                         goto out;
6519                 }
6520                 DEBUG(4, ("we have:[%d] drivers in environment"
6521                           " [%s] and version [%d]\n",
6522                           num_drivers, architecture, version));
6523
6524                 if (num_drivers != 0) {
6525                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6526                                                     union spoolss_DriverInfo,
6527                                                     count + num_drivers);
6528                         if (!info) {
6529                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6530                                         "failed to enlarge driver info buffer!\n"));
6531                                 result = WERR_NOMEM;
6532                                 goto out;
6533                         }
6534                 }
6535
6536                 for (i = 0; i < num_drivers; i++) {
6537                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6538
6539                         result = winreg_get_driver(mem_ctx, server_info,
6540                                                    architecture, drivers[i],
6541                                                    version, &driver);
6542                         if (!W_ERROR_IS_OK(result)) {
6543                                 goto out;
6544                         }
6545
6546                         switch (level) {
6547                         case 1:
6548                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6549                                                                    driver, servername);
6550                                 break;
6551                         case 2:
6552                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6553                                                                    driver, servername);
6554                                 break;
6555                         case 3:
6556                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6557                                                                    driver, servername);
6558                                 break;
6559                         case 4:
6560                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6561                                                                    driver, servername);
6562                                 break;
6563                         case 5:
6564                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6565                                                                    driver, servername);
6566                                 break;
6567                         case 6:
6568                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6569                                                                    driver, servername);
6570                                 break;
6571                         case 8:
6572                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6573                                                                    driver, servername);
6574                                 break;
6575                         default:
6576                                 result = WERR_UNKNOWN_LEVEL;
6577                                 break;
6578                         }
6579
6580                         TALLOC_FREE(driver);
6581
6582                         if (!W_ERROR_IS_OK(result)) {
6583                                 goto out;
6584                         }
6585                 }
6586
6587                 count += num_drivers;
6588                 TALLOC_FREE(drivers);
6589         }
6590
6591  out:
6592         TALLOC_FREE(drivers);
6593
6594         if (!W_ERROR_IS_OK(result)) {
6595                 TALLOC_FREE(info);
6596                 return result;
6597         }
6598
6599         *info_p = info;
6600         *count_p = count;
6601
6602         return WERR_OK;
6603 }
6604
6605 /****************************************************************************
6606  Enumerates all printer drivers by level.
6607 ****************************************************************************/
6608
6609 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6610                                        struct auth_serversupplied_info *server_info,
6611                                        const char *servername,
6612                                        const char *architecture,
6613                                        uint32_t level,
6614                                        union spoolss_DriverInfo **info_p,
6615                                        uint32_t *count_p)
6616 {
6617         uint32_t a,i;
6618         WERROR result = WERR_OK;
6619
6620         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6621
6622                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6623
6624                         union spoolss_DriverInfo *info = NULL;
6625                         uint32_t count = 0;
6626
6627                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6628                                                                           server_info,
6629                                                                           servername,
6630                                                                           archi_table[a].long_archi,
6631                                                                           level,
6632                                                                           &info,
6633                                                                           &count);
6634                         if (!W_ERROR_IS_OK(result)) {
6635                                 continue;
6636                         }
6637
6638                         for (i=0; i < count; i++) {
6639                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6640                                              info[i], info_p, count_p);
6641                         }
6642                 }
6643
6644                 return result;
6645         }
6646
6647         return enumprinterdrivers_level_by_architecture(mem_ctx,
6648                                                         server_info,
6649                                                         servername,
6650                                                         architecture,
6651                                                         level,
6652                                                         info_p,
6653                                                         count_p);
6654 }
6655
6656 /****************************************************************
6657  _spoolss_EnumPrinterDrivers
6658 ****************************************************************/
6659
6660 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6661                                    struct spoolss_EnumPrinterDrivers *r)
6662 {
6663         const char *cservername;
6664         WERROR result;
6665
6666         /* that's an [in out] buffer */
6667
6668         if (!r->in.buffer && (r->in.offered != 0)) {
6669                 return WERR_INVALID_PARAM;
6670         }
6671
6672         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6673
6674         *r->out.needed = 0;
6675         *r->out.count = 0;
6676         *r->out.info = NULL;
6677
6678         cservername = canon_servername(r->in.server);
6679
6680         if (!is_myname_or_ipaddr(cservername)) {
6681                 return WERR_UNKNOWN_PRINTER_DRIVER;
6682         }
6683
6684         result = enumprinterdrivers_level(p->mem_ctx,
6685                                           p->server_info,
6686                                           cservername,
6687                                           r->in.environment,
6688                                           r->in.level,
6689                                           r->out.info,
6690                                           r->out.count);
6691         if (!W_ERROR_IS_OK(result)) {
6692                 return result;
6693         }
6694
6695         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6696                                                      spoolss_EnumPrinterDrivers, 
6697                                                      *r->out.info, r->in.level,
6698                                                      *r->out.count);
6699         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6700         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6701
6702         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6703 }
6704
6705 /****************************************************************
6706  _spoolss_EnumForms
6707 ****************************************************************/
6708
6709 WERROR _spoolss_EnumForms(pipes_struct *p,
6710                           struct spoolss_EnumForms *r)
6711 {
6712         WERROR result;
6713
6714         *r->out.count = 0;
6715         *r->out.needed = 0;
6716         *r->out.info = NULL;
6717
6718         /* that's an [in out] buffer */
6719
6720         if (!r->in.buffer && (r->in.offered != 0) ) {
6721                 return WERR_INVALID_PARAM;
6722         }
6723
6724         DEBUG(4,("_spoolss_EnumForms\n"));
6725         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6726         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6727
6728         switch (r->in.level) {
6729         case 1:
6730                 result = winreg_printer_enumforms1(p->mem_ctx,
6731                                                    p->server_info,
6732                                                    r->out.count,
6733                                                    r->out.info);
6734                 break;
6735         default:
6736                 result = WERR_UNKNOWN_LEVEL;
6737                 break;
6738         }
6739
6740         if (!W_ERROR_IS_OK(result)) {
6741                 return result;
6742         }
6743
6744         if (*r->out.count == 0) {
6745                 return WERR_NO_MORE_ITEMS;
6746         }
6747
6748         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6749                                                      spoolss_EnumForms, 
6750                                                      *r->out.info, r->in.level,
6751                                                      *r->out.count);
6752         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6753         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6754
6755         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6756 }
6757
6758 /****************************************************************
6759  _spoolss_GetForm
6760 ****************************************************************/
6761
6762 WERROR _spoolss_GetForm(pipes_struct *p,
6763                         struct spoolss_GetForm *r)
6764 {
6765         WERROR result;
6766
6767         /* that's an [in out] buffer */
6768
6769         if (!r->in.buffer && (r->in.offered != 0)) {
6770                 return WERR_INVALID_PARAM;
6771         }
6772
6773         DEBUG(4,("_spoolss_GetForm\n"));
6774         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6775         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6776
6777         switch (r->in.level) {
6778         case 1:
6779                 result = winreg_printer_getform1(p->mem_ctx,
6780                                                  p->server_info,
6781                                                  r->in.form_name,
6782                                                  &r->out.info->info1);
6783                 break;
6784         default:
6785                 result = WERR_UNKNOWN_LEVEL;
6786                 break;
6787         }
6788
6789         if (!W_ERROR_IS_OK(result)) {
6790                 TALLOC_FREE(r->out.info);
6791                 return result;
6792         }
6793
6794         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6795                                                r->out.info, r->in.level);
6796         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6797
6798         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6799 }
6800
6801 /****************************************************************************
6802 ****************************************************************************/
6803
6804 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6805                           struct spoolss_PortInfo1 *r,
6806                           const char *name)
6807 {
6808         r->port_name = talloc_strdup(mem_ctx, name);
6809         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6810
6811         return WERR_OK;
6812 }
6813
6814 /****************************************************************************
6815  TODO: This probably needs distinguish between TCP/IP and Local ports
6816  somehow.
6817 ****************************************************************************/
6818
6819 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6820                           struct spoolss_PortInfo2 *r,
6821                           const char *name)
6822 {
6823         r->port_name = talloc_strdup(mem_ctx, name);
6824         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6825
6826         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6827         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6828
6829         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6830         W_ERROR_HAVE_NO_MEMORY(r->description);
6831
6832         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6833         r->reserved = 0;
6834
6835         return WERR_OK;
6836 }
6837
6838
6839 /****************************************************************************
6840  wrapper around the enumer ports command
6841 ****************************************************************************/
6842
6843 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6844 {
6845         char *cmd = lp_enumports_cmd();
6846         char **qlines = NULL;
6847         char *command = NULL;
6848         int numlines;
6849         int ret;
6850         int fd;
6851
6852         *count = 0;
6853         *lines = NULL;
6854
6855         /* if no hook then just fill in the default port */
6856
6857         if ( !*cmd ) {
6858                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6859                         return WERR_NOMEM;
6860                 }
6861                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6862                         TALLOC_FREE(qlines);
6863                         return WERR_NOMEM;
6864                 }
6865                 qlines[1] = NULL;
6866                 numlines = 1;
6867         }
6868         else {
6869                 /* we have a valid enumport command */
6870
6871                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6872                 if (!command) {
6873                         return WERR_NOMEM;
6874                 }
6875
6876                 DEBUG(10,("Running [%s]\n", command));
6877                 ret = smbrun(command, &fd);
6878                 DEBUG(10,("Returned [%d]\n", ret));
6879                 TALLOC_FREE(command);
6880                 if (ret != 0) {
6881                         if (fd != -1) {
6882                                 close(fd);
6883                         }
6884                         return WERR_ACCESS_DENIED;
6885                 }
6886
6887                 numlines = 0;
6888                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6889                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6890                 close(fd);
6891         }
6892
6893         *count = numlines;
6894         *lines = qlines;
6895
6896         return WERR_OK;
6897 }
6898
6899 /****************************************************************************
6900  enumports level 1.
6901 ****************************************************************************/
6902
6903 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6904                                 union spoolss_PortInfo **info_p,
6905                                 uint32_t *count)
6906 {
6907         union spoolss_PortInfo *info = NULL;
6908         int i=0;
6909         WERROR result = WERR_OK;
6910         char **qlines = NULL;
6911         int numlines = 0;
6912
6913         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6914         if (!W_ERROR_IS_OK(result)) {
6915                 goto out;
6916         }
6917
6918         if (numlines) {
6919                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6920                 if (!info) {
6921                         DEBUG(10,("Returning WERR_NOMEM\n"));
6922                         result = WERR_NOMEM;
6923                         goto out;
6924                 }
6925
6926                 for (i=0; i<numlines; i++) {
6927                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6928                         result = fill_port_1(info, &info[i].info1, qlines[i]);
6929                         if (!W_ERROR_IS_OK(result)) {
6930                                 goto out;
6931                         }
6932                 }
6933         }
6934         TALLOC_FREE(qlines);
6935
6936 out:
6937         if (!W_ERROR_IS_OK(result)) {
6938                 TALLOC_FREE(info);
6939                 TALLOC_FREE(qlines);
6940                 *count = 0;
6941                 *info_p = NULL;
6942                 return result;
6943         }
6944
6945         *info_p = info;
6946         *count = numlines;
6947
6948         return WERR_OK;
6949 }
6950
6951 /****************************************************************************
6952  enumports level 2.
6953 ****************************************************************************/
6954
6955 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6956                                 union spoolss_PortInfo **info_p,
6957                                 uint32_t *count)
6958 {
6959         union spoolss_PortInfo *info = NULL;
6960         int i=0;
6961         WERROR result = WERR_OK;
6962         char **qlines = NULL;
6963         int numlines = 0;
6964
6965         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6966         if (!W_ERROR_IS_OK(result)) {
6967                 goto out;
6968         }
6969
6970         if (numlines) {
6971                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6972                 if (!info) {
6973                         DEBUG(10,("Returning WERR_NOMEM\n"));
6974                         result = WERR_NOMEM;
6975                         goto out;
6976                 }
6977
6978                 for (i=0; i<numlines; i++) {
6979                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6980                         result = fill_port_2(info, &info[i].info2, qlines[i]);
6981                         if (!W_ERROR_IS_OK(result)) {
6982                                 goto out;
6983                         }
6984                 }
6985         }
6986         TALLOC_FREE(qlines);
6987
6988 out:
6989         if (!W_ERROR_IS_OK(result)) {
6990                 TALLOC_FREE(info);
6991                 TALLOC_FREE(qlines);
6992                 *count = 0;
6993                 *info_p = NULL;
6994                 return result;
6995         }
6996
6997         *info_p = info;
6998         *count = numlines;
6999
7000         return WERR_OK;
7001 }
7002
7003 /****************************************************************
7004  _spoolss_EnumPorts
7005 ****************************************************************/
7006
7007 WERROR _spoolss_EnumPorts(pipes_struct *p,
7008                           struct spoolss_EnumPorts *r)
7009 {
7010         WERROR result;
7011
7012         /* that's an [in out] buffer */
7013
7014         if (!r->in.buffer && (r->in.offered != 0)) {
7015                 return WERR_INVALID_PARAM;
7016         }
7017
7018         DEBUG(4,("_spoolss_EnumPorts\n"));
7019
7020         *r->out.count = 0;
7021         *r->out.needed = 0;
7022         *r->out.info = NULL;
7023
7024         switch (r->in.level) {
7025         case 1:
7026                 result = enumports_level_1(p->mem_ctx, r->out.info,
7027                                            r->out.count);
7028                 break;
7029         case 2:
7030                 result = enumports_level_2(p->mem_ctx, r->out.info,
7031                                            r->out.count);
7032                 break;
7033         default:
7034                 return WERR_UNKNOWN_LEVEL;
7035         }
7036
7037         if (!W_ERROR_IS_OK(result)) {
7038                 return result;
7039         }
7040
7041         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7042                                                      spoolss_EnumPorts, 
7043                                                      *r->out.info, r->in.level,
7044                                                      *r->out.count);
7045         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7046         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7047
7048         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7049 }
7050
7051 /****************************************************************************
7052 ****************************************************************************/
7053
7054 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7055                                            const char *server,
7056                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7057                                            struct spoolss_DeviceMode *devmode,
7058                                            struct security_descriptor *secdesc,
7059                                            struct spoolss_UserLevelCtr *user_ctr,
7060                                            struct policy_handle *handle)
7061 {
7062         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7063         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7064         int     snum;
7065         WERROR err = WERR_OK;
7066
7067         /* samba does not have a concept of local, non-shared printers yet, so
7068          * make sure we always setup sharename - gd */
7069         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7070             (info2->printername != NULL && info2->printername[0] != '\0')) {
7071                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7072                         "no sharename has been set, setting printername %s as sharename\n",
7073                         info2->printername));
7074                 info2->sharename = info2->printername;
7075         }
7076
7077         /* check to see if the printer already exists */
7078         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7079                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7080                         info2->sharename));
7081                 return WERR_PRINTER_ALREADY_EXISTS;
7082         }
7083
7084         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7085                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7086                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7087                                 info2->printername));
7088                         return WERR_PRINTER_ALREADY_EXISTS;
7089                 }
7090         }
7091
7092         /* validate printer info struct */
7093         if (!info2->printername || strlen(info2->printername) == 0) {
7094                 return WERR_INVALID_PRINTER_NAME;
7095         }
7096         if (!info2->portname || strlen(info2->portname) == 0) {
7097                 return WERR_UNKNOWN_PORT;
7098         }
7099         if (!info2->drivername || strlen(info2->drivername) == 0) {
7100                 return WERR_UNKNOWN_PRINTER_DRIVER;
7101         }
7102         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7103                 return WERR_UNKNOWN_PRINTPROCESSOR;
7104         }
7105
7106         /* FIXME!!!  smbd should check to see if the driver is installed before
7107            trying to add a printer like this  --jerry */
7108
7109         if (*lp_addprinter_cmd() ) {
7110                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7111                                        info2) ) {
7112                         return WERR_ACCESS_DENIED;
7113                 }
7114         } else {
7115                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7116                         "smb.conf parameter \"addprinter command\" is defined. This"
7117                         "parameter must exist for this call to succeed\n",
7118                         info2->sharename ));
7119         }
7120
7121         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7122                 return WERR_ACCESS_DENIED;
7123         }
7124
7125         /* you must be a printer admin to add a new printer */
7126         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7127                 return WERR_ACCESS_DENIED;
7128         }
7129
7130         /*
7131          * Do sanity check on the requested changes for Samba.
7132          */
7133
7134         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7135                 return WERR_INVALID_PARAM;
7136         }
7137
7138         if (devmode == NULL) {
7139                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7140         }
7141
7142         err = winreg_update_printer(p->mem_ctx,
7143                                     p->server_info,
7144                                     info2->sharename,
7145                                     info2_mask,
7146                                     info2,
7147                                     devmode,
7148                                     secdesc);
7149         if (!W_ERROR_IS_OK(err)) {
7150                 return err;
7151         }
7152
7153         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7154                 /* Handle open failed - remove addition. */
7155                 ZERO_STRUCTP(handle);
7156                 return WERR_ACCESS_DENIED;
7157         }
7158
7159         return WERR_OK;
7160 }
7161
7162 /****************************************************************
7163  _spoolss_AddPrinterEx
7164 ****************************************************************/
7165
7166 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7167                              struct spoolss_AddPrinterEx *r)
7168 {
7169         switch (r->in.info_ctr->level) {
7170         case 1:
7171                 /* we don't handle yet */
7172                 /* but I know what to do ... */
7173                 return WERR_UNKNOWN_LEVEL;
7174         case 2:
7175                 return spoolss_addprinterex_level_2(p, r->in.server,
7176                                                     r->in.info_ctr,
7177                                                     r->in.devmode_ctr->devmode,
7178                                                     r->in.secdesc_ctr->sd,
7179                                                     r->in.userlevel_ctr,
7180                                                     r->out.handle);
7181         default:
7182                 return WERR_UNKNOWN_LEVEL;
7183         }
7184 }
7185
7186 /****************************************************************
7187  _spoolss_AddPrinter
7188 ****************************************************************/
7189
7190 WERROR _spoolss_AddPrinter(pipes_struct *p,
7191                            struct spoolss_AddPrinter *r)
7192 {
7193         struct spoolss_AddPrinterEx a;
7194         struct spoolss_UserLevelCtr userlevel_ctr;
7195
7196         ZERO_STRUCT(userlevel_ctr);
7197
7198         userlevel_ctr.level = 1;
7199
7200         a.in.server             = r->in.server;
7201         a.in.info_ctr           = r->in.info_ctr;
7202         a.in.devmode_ctr        = r->in.devmode_ctr;
7203         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7204         a.in.userlevel_ctr      = &userlevel_ctr;
7205         a.out.handle            = r->out.handle;
7206
7207         return _spoolss_AddPrinterEx(p, &a);
7208 }
7209
7210 /****************************************************************
7211  _spoolss_AddPrinterDriverEx
7212 ****************************************************************/
7213
7214 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7215                                    struct spoolss_AddPrinterDriverEx *r)
7216 {
7217         WERROR err = WERR_OK;
7218         const char *driver_name = NULL;
7219         uint32_t version;
7220         const char *fn;
7221
7222         switch (p->opnum) {
7223                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7224                         fn = "_spoolss_AddPrinterDriver";
7225                         break;
7226                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7227                         fn = "_spoolss_AddPrinterDriverEx";
7228                         break;
7229                 default:
7230                         return WERR_INVALID_PARAM;
7231         }
7232
7233         /*
7234          * we only support the semantics of AddPrinterDriver()
7235          * i.e. only copy files that are newer than existing ones
7236          */
7237
7238         if (r->in.flags == 0) {
7239                 return WERR_INVALID_PARAM;
7240         }
7241
7242         if (r->in.flags != APD_COPY_NEW_FILES) {
7243                 return WERR_ACCESS_DENIED;
7244         }
7245
7246         /* FIXME */
7247         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7248                 /* Clever hack from Martin Zielinski <mz@seh.de>
7249                  * to allow downgrade from level 8 (Vista).
7250                  */
7251                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7252                         r->in.info_ctr->level));
7253                 return WERR_UNKNOWN_LEVEL;
7254         }
7255
7256         DEBUG(5,("Cleaning driver's information\n"));
7257         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7258         if (!W_ERROR_IS_OK(err))
7259                 goto done;
7260
7261         DEBUG(5,("Moving driver to final destination\n"));
7262         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7263                                                               &err)) ) {
7264                 goto done;
7265         }
7266
7267         err = winreg_add_driver(p->mem_ctx, p->server_info,
7268                                 r->in.info_ctr, &driver_name, &version);
7269         if (!W_ERROR_IS_OK(err)) {
7270                 goto done;
7271         }
7272
7273         /*
7274          * I think this is where he DrvUpgradePrinter() hook would be
7275          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7276          * server.  Right now, we just need to send ourselves a message
7277          * to update each printer bound to this driver.   --jerry
7278          */
7279
7280         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7281                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7282                         fn, driver_name));
7283         }
7284
7285 done:
7286         return err;
7287 }
7288
7289 /****************************************************************
7290  _spoolss_AddPrinterDriver
7291 ****************************************************************/
7292
7293 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7294                                  struct spoolss_AddPrinterDriver *r)
7295 {
7296         struct spoolss_AddPrinterDriverEx a;
7297
7298         switch (r->in.info_ctr->level) {
7299         case 2:
7300         case 3:
7301         case 4:
7302         case 5:
7303                 break;
7304         default:
7305                 return WERR_UNKNOWN_LEVEL;
7306         }
7307
7308         a.in.servername         = r->in.servername;
7309         a.in.info_ctr           = r->in.info_ctr;
7310         a.in.flags              = APD_COPY_NEW_FILES;
7311
7312         return _spoolss_AddPrinterDriverEx(p, &a);
7313 }
7314
7315 /****************************************************************************
7316 ****************************************************************************/
7317
7318 struct _spoolss_paths {
7319         int type;
7320         const char *share;
7321         const char *dir;
7322 };
7323
7324 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7325
7326 static const struct _spoolss_paths spoolss_paths[]= {
7327         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7328         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7329 };
7330
7331 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7332                                           const char *servername,
7333                                           const char *environment,
7334                                           int component,
7335                                           char **path)
7336 {
7337         const char *pservername = NULL;
7338         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7339         const char *short_archi;
7340
7341         *path = NULL;
7342
7343         /* environment may be empty */
7344         if (environment && strlen(environment)) {
7345                 long_archi = environment;
7346         }
7347
7348         /* servername may be empty */
7349         if (servername && strlen(servername)) {
7350                 pservername = canon_servername(servername);
7351
7352                 if (!is_myname_or_ipaddr(pservername)) {
7353                         return WERR_INVALID_PARAM;
7354                 }
7355         }
7356
7357         if (!(short_archi = get_short_archi(long_archi))) {
7358                 return WERR_INVALID_ENVIRONMENT;
7359         }
7360
7361         switch (component) {
7362         case SPOOLSS_PRTPROCS_PATH:
7363         case SPOOLSS_DRIVER_PATH:
7364                 if (pservername) {
7365                         *path = talloc_asprintf(mem_ctx,
7366                                         "\\\\%s\\%s\\%s",
7367                                         pservername,
7368                                         spoolss_paths[component].share,
7369                                         short_archi);
7370                 } else {
7371                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7372                                         SPOOLSS_DEFAULT_SERVER_PATH,
7373                                         spoolss_paths[component].dir,
7374                                         short_archi);
7375                 }
7376                 break;
7377         default:
7378                 return WERR_INVALID_PARAM;
7379         }
7380
7381         if (!*path) {
7382                 return WERR_NOMEM;
7383         }
7384
7385         return WERR_OK;
7386 }
7387
7388 /****************************************************************************
7389 ****************************************************************************/
7390
7391 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7392                                           const char *servername,
7393                                           const char *environment,
7394                                           struct spoolss_DriverDirectoryInfo1 *r)
7395 {
7396         WERROR werr;
7397         char *path = NULL;
7398
7399         werr = compose_spoolss_server_path(mem_ctx,
7400                                            servername,
7401                                            environment,
7402                                            SPOOLSS_DRIVER_PATH,
7403                                            &path);
7404         if (!W_ERROR_IS_OK(werr)) {
7405                 return werr;
7406         }
7407
7408         DEBUG(4,("printer driver directory: [%s]\n", path));
7409
7410         r->directory_name = path;
7411
7412         return WERR_OK;
7413 }
7414
7415 /****************************************************************
7416  _spoolss_GetPrinterDriverDirectory
7417 ****************************************************************/
7418
7419 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7420                                           struct spoolss_GetPrinterDriverDirectory *r)
7421 {
7422         WERROR werror;
7423
7424         /* that's an [in out] buffer */
7425
7426         if (!r->in.buffer && (r->in.offered != 0)) {
7427                 return WERR_INVALID_PARAM;
7428         }
7429
7430         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7431                 r->in.level));
7432
7433         *r->out.needed = 0;
7434
7435         /* r->in.level is ignored */
7436
7437         werror = getprinterdriverdir_level_1(p->mem_ctx,
7438                                              r->in.server,
7439                                              r->in.environment,
7440                                              &r->out.info->info1);
7441         if (!W_ERROR_IS_OK(werror)) {
7442                 TALLOC_FREE(r->out.info);
7443                 return werror;
7444         }
7445
7446         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7447                                                r->out.info, r->in.level);
7448         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7449
7450         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7451 }
7452
7453 /****************************************************************
7454  _spoolss_EnumPrinterData
7455 ****************************************************************/
7456
7457 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7458                                 struct spoolss_EnumPrinterData *r)
7459 {
7460         WERROR result;
7461         struct spoolss_EnumPrinterDataEx r2;
7462         uint32_t count;
7463         struct spoolss_PrinterEnumValues *info, *val = NULL;
7464         uint32_t needed;
7465
7466         r2.in.handle    = r->in.handle;
7467         r2.in.key_name  = "PrinterDriverData";
7468         r2.in.offered   = 0;
7469         r2.out.count    = &count;
7470         r2.out.info     = &info;
7471         r2.out.needed   = &needed;
7472
7473         result = _spoolss_EnumPrinterDataEx(p, &r2);
7474         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7475                 r2.in.offered = needed;
7476                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7477         }
7478         if (!W_ERROR_IS_OK(result)) {
7479                 return result;
7480         }
7481
7482         /*
7483          * The NT machine wants to know the biggest size of value and data
7484          *
7485          * cf: MSDN EnumPrinterData remark section
7486          */
7487
7488         if (!r->in.value_offered && !r->in.data_offered) {
7489                 uint32_t biggest_valuesize = 0;
7490                 uint32_t biggest_datasize = 0;
7491                 int i, name_length;
7492
7493                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7494
7495                 for (i=0; i<count; i++) {
7496
7497                         name_length = strlen(info[i].value_name);
7498                         if (strlen(info[i].value_name) > biggest_valuesize) {
7499                                 biggest_valuesize = name_length;
7500                         }
7501
7502                         if (info[i].data_length > biggest_datasize) {
7503                                 biggest_datasize = info[i].data_length;
7504                         }
7505
7506                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7507                                 biggest_datasize));
7508                 }
7509
7510                 /* the value is an UNICODE string but real_value_size is the length
7511                    in bytes including the trailing 0 */
7512
7513                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7514                 *r->out.data_needed  = biggest_datasize;
7515
7516                 DEBUG(6,("final values: [%d], [%d]\n",
7517                         *r->out.value_needed, *r->out.data_needed));
7518
7519                 return WERR_OK;
7520         }
7521
7522         if (r->in.enum_index < count) {
7523                 val = &info[r->in.enum_index];
7524         }
7525
7526         if (val == NULL) {
7527                 /* out_value should default to "" or else NT4 has
7528                    problems unmarshalling the response */
7529
7530                 if (r->in.value_offered) {
7531                         *r->out.value_needed = 1;
7532                         r->out.value_name = talloc_strdup(r, "");
7533                         if (!r->out.value_name) {
7534                                 return WERR_NOMEM;
7535                         }
7536                 } else {
7537                         r->out.value_name = NULL;
7538                         *r->out.value_needed = 0;
7539                 }
7540
7541                 /* the data is counted in bytes */
7542
7543                 *r->out.data_needed = r->in.data_offered;
7544
7545                 result = WERR_NO_MORE_ITEMS;
7546         } else {
7547                 /*
7548                  * the value is:
7549                  * - counted in bytes in the request
7550                  * - counted in UNICODE chars in the max reply
7551                  * - counted in bytes in the real size
7552                  *
7553                  * take a pause *before* coding not *during* coding
7554                  */
7555
7556                 /* name */
7557                 if (r->in.value_offered) {
7558                         r->out.value_name = talloc_strdup(r, val->value_name);
7559                         if (!r->out.value_name) {
7560                                 return WERR_NOMEM;
7561                         }
7562                         *r->out.value_needed = val->value_name_len;
7563                 } else {
7564                         r->out.value_name = NULL;
7565                         *r->out.value_needed = 0;
7566                 }
7567
7568                 /* type */
7569
7570                 *r->out.type = val->type;
7571
7572                 /* data - counted in bytes */
7573
7574                 /*
7575                  * See the section "Dynamically Typed Query Parameters"
7576                  * in MS-RPRN.
7577                  */
7578
7579                 if (r->out.data && val->data && val->data->data &&
7580                                 val->data_length && r->in.data_offered) {
7581                         memcpy(r->out.data, val->data->data,
7582                                 MIN(val->data_length,r->in.data_offered));
7583                 }
7584
7585                 *r->out.data_needed = val->data_length;
7586
7587                 result = WERR_OK;
7588         }
7589
7590         return result;
7591 }
7592
7593 /****************************************************************
7594  _spoolss_SetPrinterData
7595 ****************************************************************/
7596
7597 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7598                                struct spoolss_SetPrinterData *r)
7599 {
7600         struct spoolss_SetPrinterDataEx r2;
7601
7602         r2.in.handle            = r->in.handle;
7603         r2.in.key_name          = "PrinterDriverData";
7604         r2.in.value_name        = r->in.value_name;
7605         r2.in.type              = r->in.type;
7606         r2.in.data              = r->in.data;
7607         r2.in.offered           = r->in.offered;
7608
7609         return _spoolss_SetPrinterDataEx(p, &r2);
7610 }
7611
7612 /****************************************************************
7613  _spoolss_ResetPrinter
7614 ****************************************************************/
7615
7616 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7617                              struct spoolss_ResetPrinter *r)
7618 {
7619         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7620         int             snum;
7621
7622         DEBUG(5,("_spoolss_ResetPrinter\n"));
7623
7624         /*
7625          * All we do is to check to see if the handle and queue is valid.
7626          * This call really doesn't mean anything to us because we only
7627          * support RAW printing.   --jerry
7628          */
7629
7630         if (!Printer) {
7631                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7632                         OUR_HANDLE(r->in.handle)));
7633                 return WERR_BADFID;
7634         }
7635
7636         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7637                 return WERR_BADFID;
7638
7639
7640         /* blindly return success */
7641         return WERR_OK;
7642 }
7643
7644 /****************************************************************
7645  _spoolss_DeletePrinterData
7646 ****************************************************************/
7647
7648 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7649                                   struct spoolss_DeletePrinterData *r)
7650 {
7651         struct spoolss_DeletePrinterDataEx r2;
7652
7653         r2.in.handle            = r->in.handle;
7654         r2.in.key_name          = "PrinterDriverData";
7655         r2.in.value_name        = r->in.value_name;
7656
7657         return _spoolss_DeletePrinterDataEx(p, &r2);
7658 }
7659
7660 /****************************************************************
7661  _spoolss_AddForm
7662 ****************************************************************/
7663
7664 WERROR _spoolss_AddForm(pipes_struct *p,
7665                         struct spoolss_AddForm *r)
7666 {
7667         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7668         int snum = -1;
7669         WERROR status = WERR_OK;
7670         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7671
7672         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7673
7674         DEBUG(5,("_spoolss_AddForm\n"));
7675
7676         if (!Printer) {
7677                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7678                         OUR_HANDLE(r->in.handle)));
7679                 return WERR_BADFID;
7680         }
7681
7682         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7683            and not a printer admin, then fail */
7684
7685         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7686              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7687              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7688                                           p->server_info->info3->base.domain.string,
7689                                           NULL,
7690                                           p->server_info->ptok,
7691                                           lp_printer_admin(snum))) {
7692                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7693                 return WERR_ACCESS_DENIED;
7694         }
7695
7696         switch (form->flags) {
7697         case SPOOLSS_FORM_USER:
7698         case SPOOLSS_FORM_BUILTIN:
7699         case SPOOLSS_FORM_PRINTER:
7700                 break;
7701         default:
7702                 return WERR_INVALID_PARAM;
7703         }
7704
7705         status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7706         if (!W_ERROR_IS_OK(status)) {
7707                 return status;
7708         }
7709
7710         /*
7711          * ChangeID must always be set if this is a printer
7712          */
7713         if (Printer->printer_type == SPLHND_PRINTER) {
7714                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7715                         return WERR_BADFID;
7716                 }
7717
7718                 status = winreg_printer_update_changeid(p->mem_ctx,
7719                                                         p->server_info,
7720                                                         lp_const_servicename(snum));
7721                 if (!W_ERROR_IS_OK(status)) {
7722                         return status;
7723                 }
7724         }
7725
7726         return status;
7727 }
7728
7729 /****************************************************************
7730  _spoolss_DeleteForm
7731 ****************************************************************/
7732
7733 WERROR _spoolss_DeleteForm(pipes_struct *p,
7734                            struct spoolss_DeleteForm *r)
7735 {
7736         const char *form_name = r->in.form_name;
7737         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7738         int snum = -1;
7739         WERROR status = WERR_OK;
7740         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7741
7742         DEBUG(5,("_spoolss_DeleteForm\n"));
7743
7744         if (!Printer) {
7745                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7746                         OUR_HANDLE(r->in.handle)));
7747                 return WERR_BADFID;
7748         }
7749
7750         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7751              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7752              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7753                                           p->server_info->info3->base.domain.string,
7754                                           NULL,
7755                                           p->server_info->ptok,
7756                                           lp_printer_admin(snum))) {
7757                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7758                 return WERR_ACCESS_DENIED;
7759         }
7760
7761         status = winreg_printer_deleteform1(p->mem_ctx,
7762                                             p->server_info,
7763                                             form_name);
7764         if (!W_ERROR_IS_OK(status)) {
7765                 return status;
7766         }
7767
7768         /*
7769          * ChangeID must always be set if this is a printer
7770          */
7771         if (Printer->printer_type == SPLHND_PRINTER) {
7772                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7773                         return WERR_BADFID;
7774                 }
7775
7776                 status = winreg_printer_update_changeid(p->mem_ctx,
7777                                                         p->server_info,
7778                                                         lp_const_servicename(snum));
7779                 if (!W_ERROR_IS_OK(status)) {
7780                         return status;
7781                 }
7782         }
7783
7784         return status;
7785 }
7786
7787 /****************************************************************
7788  _spoolss_SetForm
7789 ****************************************************************/
7790
7791 WERROR _spoolss_SetForm(pipes_struct *p,
7792                         struct spoolss_SetForm *r)
7793 {
7794         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7795         const char *form_name = r->in.form_name;
7796         int snum = -1;
7797         WERROR status = WERR_OK;
7798         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7799
7800         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7801
7802         DEBUG(5,("_spoolss_SetForm\n"));
7803
7804         if (!Printer) {
7805                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7806                         OUR_HANDLE(r->in.handle)));
7807                 return WERR_BADFID;
7808         }
7809
7810         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7811            and not a printer admin, then fail */
7812
7813         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7814              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7815              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7816                                           p->server_info->info3->base.domain.string,
7817                                           NULL,
7818                                           p->server_info->ptok,
7819                                           lp_printer_admin(snum))) {
7820                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7821                 return WERR_ACCESS_DENIED;
7822         }
7823
7824         status = winreg_printer_setform1(p->mem_ctx,
7825                                          p->server_info,
7826                                          form_name,
7827                                          form);
7828         if (!W_ERROR_IS_OK(status)) {
7829                 return status;
7830         }
7831
7832         /*
7833          * ChangeID must always be set if this is a printer
7834          */
7835         if (Printer->printer_type == SPLHND_PRINTER) {
7836                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7837                         return WERR_BADFID;
7838                 }
7839
7840                 status = winreg_printer_update_changeid(p->mem_ctx,
7841                                                         p->server_info,
7842                                                         lp_const_servicename(snum));
7843                 if (!W_ERROR_IS_OK(status)) {
7844                         return status;
7845                 }
7846         }
7847
7848         return status;
7849 }
7850
7851 /****************************************************************************
7852  fill_print_processor1
7853 ****************************************************************************/
7854
7855 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7856                                     struct spoolss_PrintProcessorInfo1 *r,
7857                                     const char *print_processor_name)
7858 {
7859         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7860         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7861
7862         return WERR_OK;
7863 }
7864
7865 /****************************************************************************
7866  enumprintprocessors level 1.
7867 ****************************************************************************/
7868
7869 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7870                                           union spoolss_PrintProcessorInfo **info_p,
7871                                           uint32_t *count)
7872 {
7873         union spoolss_PrintProcessorInfo *info;
7874         WERROR result;
7875
7876         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7877         W_ERROR_HAVE_NO_MEMORY(info);
7878
7879         *count = 1;
7880
7881         result = fill_print_processor1(info, &info[0].info1, "winprint");
7882         if (!W_ERROR_IS_OK(result)) {
7883                 goto out;
7884         }
7885
7886  out:
7887         if (!W_ERROR_IS_OK(result)) {
7888                 TALLOC_FREE(info);
7889                 *count = 0;
7890                 return result;
7891         }
7892
7893         *info_p = info;
7894
7895         return WERR_OK;
7896 }
7897
7898 /****************************************************************
7899  _spoolss_EnumPrintProcessors
7900 ****************************************************************/
7901
7902 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7903                                     struct spoolss_EnumPrintProcessors *r)
7904 {
7905         WERROR result;
7906
7907         /* that's an [in out] buffer */
7908
7909         if (!r->in.buffer && (r->in.offered != 0)) {
7910                 return WERR_INVALID_PARAM;
7911         }
7912
7913         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7914
7915         /*
7916          * Enumerate the print processors ...
7917          *
7918          * Just reply with "winprint", to keep NT happy
7919          * and I can use my nice printer checker.
7920          */
7921
7922         *r->out.count = 0;
7923         *r->out.needed = 0;
7924         *r->out.info = NULL;
7925
7926         switch (r->in.level) {
7927         case 1:
7928                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7929                                                      r->out.count);
7930                 break;
7931         default:
7932                 return WERR_UNKNOWN_LEVEL;
7933         }
7934
7935         if (!W_ERROR_IS_OK(result)) {
7936                 return result;
7937         }
7938
7939         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7940                                                      spoolss_EnumPrintProcessors,
7941                                                      *r->out.info, r->in.level,
7942                                                      *r->out.count);
7943         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7944         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7945
7946         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7947 }
7948
7949 /****************************************************************************
7950  fill_printprocdatatype1
7951 ****************************************************************************/
7952
7953 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
7954                                       struct spoolss_PrintProcDataTypesInfo1 *r,
7955                                       const char *name_array)
7956 {
7957         r->name_array = talloc_strdup(mem_ctx, name_array);
7958         W_ERROR_HAVE_NO_MEMORY(r->name_array);
7959
7960         return WERR_OK;
7961 }
7962
7963 /****************************************************************************
7964  enumprintprocdatatypes level 1.
7965 ****************************************************************************/
7966
7967 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
7968                                              union spoolss_PrintProcDataTypesInfo **info_p,
7969                                              uint32_t *count)
7970 {
7971         WERROR result;
7972         union spoolss_PrintProcDataTypesInfo *info;
7973
7974         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
7975         W_ERROR_HAVE_NO_MEMORY(info);
7976
7977         *count = 1;
7978
7979         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
7980         if (!W_ERROR_IS_OK(result)) {
7981                 goto out;
7982         }
7983
7984  out:
7985         if (!W_ERROR_IS_OK(result)) {
7986                 TALLOC_FREE(info);
7987                 *count = 0;
7988                 return result;
7989         }
7990
7991         *info_p = info;
7992
7993         return WERR_OK;
7994 }
7995
7996 /****************************************************************
7997  _spoolss_EnumPrintProcDataTypes
7998 ****************************************************************/
7999
8000 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8001                                        struct spoolss_EnumPrintProcDataTypes *r)
8002 {
8003         WERROR result;
8004
8005         /* that's an [in out] buffer */
8006
8007         if (!r->in.buffer && (r->in.offered != 0)) {
8008                 return WERR_INVALID_PARAM;
8009         }
8010
8011         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8012
8013         *r->out.count = 0;
8014         *r->out.needed = 0;
8015         *r->out.info = NULL;
8016
8017         switch (r->in.level) {
8018         case 1:
8019                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8020                                                         r->out.count);
8021                 break;
8022         default:
8023                 return WERR_UNKNOWN_LEVEL;
8024         }
8025
8026         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8027                                                      spoolss_EnumPrintProcDataTypes, 
8028                                                      *r->out.info, r->in.level,
8029                                                      *r->out.count);
8030         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8031         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8032
8033         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8034 }
8035
8036 /****************************************************************************
8037  fill_monitor_1
8038 ****************************************************************************/
8039
8040 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8041                              struct spoolss_MonitorInfo1 *r,
8042                              const char *monitor_name)
8043 {
8044         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8045         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8046
8047         return WERR_OK;
8048 }
8049
8050 /****************************************************************************
8051  fill_monitor_2
8052 ****************************************************************************/
8053
8054 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8055                              struct spoolss_MonitorInfo2 *r,
8056                              const char *monitor_name,
8057                              const char *environment,
8058                              const char *dll_name)
8059 {
8060         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8061         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8062         r->environment                  = talloc_strdup(mem_ctx, environment);
8063         W_ERROR_HAVE_NO_MEMORY(r->environment);
8064         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8065         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8066
8067         return WERR_OK;
8068 }
8069
8070 /****************************************************************************
8071  enumprintmonitors level 1.
8072 ****************************************************************************/
8073
8074 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8075                                         union spoolss_MonitorInfo **info_p,
8076                                         uint32_t *count)
8077 {
8078         union spoolss_MonitorInfo *info;
8079         WERROR result = WERR_OK;
8080
8081         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8082         W_ERROR_HAVE_NO_MEMORY(info);
8083
8084         *count = 2;
8085
8086         result = fill_monitor_1(info, &info[0].info1,
8087                                 SPL_LOCAL_PORT);
8088         if (!W_ERROR_IS_OK(result)) {
8089                 goto out;
8090         }
8091
8092         result = fill_monitor_1(info, &info[1].info1,
8093                                 SPL_TCPIP_PORT);
8094         if (!W_ERROR_IS_OK(result)) {
8095                 goto out;
8096         }
8097
8098 out:
8099         if (!W_ERROR_IS_OK(result)) {
8100                 TALLOC_FREE(info);
8101                 *count = 0;
8102                 return result;
8103         }
8104
8105         *info_p = info;
8106
8107         return WERR_OK;
8108 }
8109
8110 /****************************************************************************
8111  enumprintmonitors level 2.
8112 ****************************************************************************/
8113
8114 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8115                                         union spoolss_MonitorInfo **info_p,
8116                                         uint32_t *count)
8117 {
8118         union spoolss_MonitorInfo *info;
8119         WERROR result = WERR_OK;
8120
8121         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8122         W_ERROR_HAVE_NO_MEMORY(info);
8123
8124         *count = 2;
8125
8126         result = fill_monitor_2(info, &info[0].info2,
8127                                 SPL_LOCAL_PORT,
8128                                 "Windows NT X86", /* FIXME */
8129                                 "localmon.dll");
8130         if (!W_ERROR_IS_OK(result)) {
8131                 goto out;
8132         }
8133
8134         result = fill_monitor_2(info, &info[1].info2,
8135                                 SPL_TCPIP_PORT,
8136                                 "Windows NT X86", /* FIXME */
8137                                 "tcpmon.dll");
8138         if (!W_ERROR_IS_OK(result)) {
8139                 goto out;
8140         }
8141
8142 out:
8143         if (!W_ERROR_IS_OK(result)) {
8144                 TALLOC_FREE(info);
8145                 *count = 0;
8146                 return result;
8147         }
8148
8149         *info_p = info;
8150
8151         return WERR_OK;
8152 }
8153
8154 /****************************************************************
8155  _spoolss_EnumMonitors
8156 ****************************************************************/
8157
8158 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8159                              struct spoolss_EnumMonitors *r)
8160 {
8161         WERROR result;
8162
8163         /* that's an [in out] buffer */
8164
8165         if (!r->in.buffer && (r->in.offered != 0)) {
8166                 return WERR_INVALID_PARAM;
8167         }
8168
8169         DEBUG(5,("_spoolss_EnumMonitors\n"));
8170
8171         /*
8172          * Enumerate the print monitors ...
8173          *
8174          * Just reply with "Local Port", to keep NT happy
8175          * and I can use my nice printer checker.
8176          */
8177
8178         *r->out.count = 0;
8179         *r->out.needed = 0;
8180         *r->out.info = NULL;
8181
8182         switch (r->in.level) {
8183         case 1:
8184                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8185                                                    r->out.count);
8186                 break;
8187         case 2:
8188                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8189                                                    r->out.count);
8190                 break;
8191         default:
8192                 return WERR_UNKNOWN_LEVEL;
8193         }
8194
8195         if (!W_ERROR_IS_OK(result)) {
8196                 return result;
8197         }
8198
8199         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8200                                                      spoolss_EnumMonitors, 
8201                                                      *r->out.info, r->in.level,
8202                                                      *r->out.count);
8203         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8204         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8205
8206         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8207 }
8208
8209 /****************************************************************************
8210 ****************************************************************************/
8211
8212 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8213                              const print_queue_struct *queue,
8214                              int count, int snum,
8215                              struct spoolss_PrinterInfo2 *pinfo2,
8216                              uint32_t jobid,
8217                              struct spoolss_JobInfo1 *r)
8218 {
8219         int i = 0;
8220         bool found = false;
8221
8222         for (i=0; i<count; i++) {
8223                 if (queue[i].job == (int)jobid) {
8224                         found = true;
8225                         break;
8226                 }
8227         }
8228
8229         if (found == false) {
8230                 /* NT treats not found as bad param... yet another bad choice */
8231                 return WERR_INVALID_PARAM;
8232         }
8233
8234         return fill_job_info1(mem_ctx,
8235                               r,
8236                               &queue[i],
8237                               i,
8238                               snum,
8239                               pinfo2);
8240 }
8241
8242 /****************************************************************************
8243 ****************************************************************************/
8244
8245 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8246                              const print_queue_struct *queue,
8247                              int count, int snum,
8248                              struct spoolss_PrinterInfo2 *pinfo2,
8249                              uint32_t jobid,
8250                              struct spoolss_JobInfo2 *r)
8251 {
8252         int i = 0;
8253         bool found = false;
8254         struct spoolss_DeviceMode *devmode;
8255         WERROR result;
8256
8257         for (i=0; i<count; i++) {
8258                 if (queue[i].job == (int)jobid) {
8259                         found = true;
8260                         break;
8261                 }
8262         }
8263
8264         if (found == false) {
8265                 /* NT treats not found as bad param... yet another bad
8266                    choice */
8267                 return WERR_INVALID_PARAM;
8268         }
8269
8270         /*
8271          * if the print job does not have a DEVMODE associated with it,
8272          * just use the one for the printer. A NULL devicemode is not
8273          *  a failure condition
8274          */
8275
8276         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8277         if (!devmode) {
8278                 result = spoolss_create_default_devmode(mem_ctx,
8279                                                 pinfo2->printername,
8280                                                 &devmode);
8281                 if (!W_ERROR_IS_OK(result)) {
8282                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8283                         return result;
8284                 }
8285         }
8286
8287         return fill_job_info2(mem_ctx,
8288                               r,
8289                               &queue[i],
8290                               i,
8291                               snum,
8292                               pinfo2,
8293                               devmode);
8294 }
8295
8296 /****************************************************************
8297  _spoolss_GetJob
8298 ****************************************************************/
8299
8300 WERROR _spoolss_GetJob(pipes_struct *p,
8301                        struct spoolss_GetJob *r)
8302 {
8303         WERROR result = WERR_OK;
8304         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8305         int snum;
8306         int count;
8307         print_queue_struct      *queue = NULL;
8308         print_status_struct prt_status;
8309
8310         /* that's an [in out] buffer */
8311
8312         if (!r->in.buffer && (r->in.offered != 0)) {
8313                 return WERR_INVALID_PARAM;
8314         }
8315
8316         DEBUG(5,("_spoolss_GetJob\n"));
8317
8318         *r->out.needed = 0;
8319
8320         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8321                 return WERR_BADFID;
8322         }
8323
8324         result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
8325                                     lp_servicename(snum), &pinfo2);
8326         if (!W_ERROR_IS_OK(result)) {
8327                 return result;
8328         }
8329
8330         count = print_queue_status(snum, &queue, &prt_status);
8331
8332         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8333                      count, prt_status.status, prt_status.message));
8334
8335         switch (r->in.level) {
8336         case 1:
8337                 result = getjob_level_1(p->mem_ctx,
8338                                         queue, count, snum, pinfo2,
8339                                         r->in.job_id, &r->out.info->info1);
8340                 break;
8341         case 2:
8342                 result = getjob_level_2(p->mem_ctx,
8343                                         queue, count, snum, pinfo2,
8344                                         r->in.job_id, &r->out.info->info2);
8345                 break;
8346         default:
8347                 result = WERR_UNKNOWN_LEVEL;
8348                 break;
8349         }
8350
8351         SAFE_FREE(queue);
8352         TALLOC_FREE(pinfo2);
8353
8354         if (!W_ERROR_IS_OK(result)) {
8355                 TALLOC_FREE(r->out.info);
8356                 return result;
8357         }
8358
8359         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8360                                                                                    r->in.level);
8361         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8362
8363         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8364 }
8365
8366 /****************************************************************
8367  _spoolss_GetPrinterDataEx
8368 ****************************************************************/
8369
8370 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8371                                  struct spoolss_GetPrinterDataEx *r)
8372 {
8373
8374         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8375         const char *printer;
8376         int                     snum = 0;
8377         WERROR result = WERR_OK;
8378         DATA_BLOB blob;
8379         enum winreg_Type val_type;
8380         uint8_t *val_data;
8381         uint32_t val_size;
8382
8383
8384         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8385
8386         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8387                 r->in.key_name, r->in.value_name));
8388
8389         /* in case of problem, return some default values */
8390
8391         *r->out.needed  = 0;
8392         *r->out.type    = REG_NONE;
8393
8394         if (!Printer) {
8395                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8396                         OUR_HANDLE(r->in.handle)));
8397                 result = WERR_BADFID;
8398                 goto done;
8399         }
8400
8401         /* Is the handle to a printer or to the server? */
8402
8403         if (Printer->printer_type == SPLHND_SERVER) {
8404
8405                 union spoolss_PrinterData data;
8406
8407                 result = getprinterdata_printer_server(p->mem_ctx,
8408                                                        r->in.value_name,
8409                                                        r->out.type,
8410                                                        &data);
8411                 if (!W_ERROR_IS_OK(result)) {
8412                         return result;
8413                 }
8414
8415                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8416                                                   *r->out.type, &data);
8417                 if (!W_ERROR_IS_OK(result)) {
8418                         return result;
8419                 }
8420
8421                 *r->out.needed = blob.length;
8422
8423                 if (r->in.offered >= *r->out.needed) {
8424                         memcpy(r->out.data, blob.data, blob.length);
8425                 }
8426
8427                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8428         }
8429
8430         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8431                 return WERR_BADFID;
8432         }
8433         printer = lp_const_servicename(snum);
8434
8435         /* check to see if the keyname is valid */
8436         if (!strlen(r->in.key_name)) {
8437                 return WERR_INVALID_PARAM;
8438         }
8439
8440         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8441         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8442             strequal(r->in.value_name, "ChangeId")) {
8443                 *r->out.type = REG_DWORD;
8444                 *r->out.needed = 4;
8445                 if (r->in.offered >= *r->out.needed) {
8446                         uint32_t changeid = 0;
8447
8448                         result = winreg_printer_get_changeid(p->mem_ctx,
8449                                                              p->server_info,
8450                                                              printer,
8451                                                              &changeid);
8452                         if (!W_ERROR_IS_OK(result)) {
8453                                 return result;
8454                         }
8455
8456                         SIVAL(r->out.data, 0, changeid);
8457                         result = WERR_OK;
8458                 }
8459                 goto done;
8460         }
8461
8462         result = winreg_get_printer_dataex(p->mem_ctx,
8463                                            p->server_info,
8464                                            printer,
8465                                            r->in.key_name,
8466                                            r->in.value_name,
8467                                            &val_type,
8468                                            &val_data,
8469                                            &val_size);
8470         if (!W_ERROR_IS_OK(result)) {
8471                 return result;
8472         }
8473
8474         *r->out.needed = val_size;
8475         *r->out.type = val_type;
8476
8477         if (r->in.offered >= *r->out.needed) {
8478                 memcpy(r->out.data, val_data, val_size);
8479         }
8480
8481  done:
8482         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8483         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8484
8485         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8486 }
8487
8488 /****************************************************************
8489  _spoolss_SetPrinterDataEx
8490 ****************************************************************/
8491
8492 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8493                                  struct spoolss_SetPrinterDataEx *r)
8494 {
8495         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8496         int                     snum = 0;
8497         WERROR                  result = WERR_OK;
8498         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8499         char                    *oid_string;
8500
8501         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8502
8503         /* From MSDN documentation of SetPrinterDataEx: pass request to
8504            SetPrinterData if key is "PrinterDriverData" */
8505
8506         if (!Printer) {
8507                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8508                         OUR_HANDLE(r->in.handle)));
8509                 return WERR_BADFID;
8510         }
8511
8512         if (Printer->printer_type == SPLHND_SERVER) {
8513                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8514                         "Not implemented for server handles yet\n"));
8515                 return WERR_INVALID_PARAM;
8516         }
8517
8518         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8519                 return WERR_BADFID;
8520         }
8521
8522         /*
8523          * Access check : NT returns "access denied" if you make a
8524          * SetPrinterData call without the necessary privildge.
8525          * we were originally returning OK if nothing changed
8526          * which made Win2k issue **a lot** of SetPrinterData
8527          * when connecting to a printer  --jerry
8528          */
8529
8530         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8531                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8532                         "change denied by handle access permissions\n"));
8533                 return WERR_ACCESS_DENIED;
8534         }
8535
8536         result = winreg_get_printer(Printer, p->server_info,
8537                                     Printer->servername,
8538                                     lp_servicename(snum),
8539                                     &pinfo2);
8540         if (!W_ERROR_IS_OK(result)) {
8541                 return result;
8542         }
8543
8544         /* check for OID in valuename */
8545
8546         oid_string = strchr(r->in.value_name, ',');
8547         if (oid_string) {
8548                 *oid_string = '\0';
8549                 oid_string++;
8550         }
8551
8552         /* save the registry data */
8553
8554         result = winreg_set_printer_dataex(p->mem_ctx,
8555                                            p->server_info,
8556                                            pinfo2->sharename,
8557                                            r->in.key_name,
8558                                            r->in.value_name,
8559                                            r->in.type,
8560                                            r->in.data,
8561                                            r->in.offered);
8562
8563         if (W_ERROR_IS_OK(result)) {
8564                 /* save the OID if one was specified */
8565                 if (oid_string) {
8566                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8567                                 r->in.key_name, SPOOL_OID_KEY);
8568                         if (!str) {
8569                                 result = WERR_NOMEM;
8570                                 goto done;
8571                         }
8572
8573                         /*
8574                          * I'm not checking the status here on purpose.  Don't know
8575                          * if this is right, but I'm returning the status from the
8576                          * previous set_printer_dataex() call.  I have no idea if
8577                          * this is right.    --jerry
8578                          */
8579                         winreg_set_printer_dataex(p->mem_ctx,
8580                                                   p->server_info,
8581                                                   pinfo2->sharename,
8582                                                   str,
8583                                                   r->in.value_name,
8584                                                   REG_SZ,
8585                                                   (uint8_t *) oid_string,
8586                                                   strlen(oid_string) + 1);
8587                 }
8588
8589                 result = winreg_printer_update_changeid(p->mem_ctx,
8590                                                         p->server_info,
8591                                                         lp_const_servicename(snum));
8592
8593         }
8594
8595 done:
8596         talloc_free(pinfo2);
8597         return result;
8598 }
8599
8600 /****************************************************************
8601  _spoolss_DeletePrinterDataEx
8602 ****************************************************************/
8603
8604 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8605                                     struct spoolss_DeletePrinterDataEx *r)
8606 {
8607         const char *printer;
8608         int             snum=0;
8609         WERROR          status = WERR_OK;
8610         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8611
8612         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8613
8614         if (!Printer) {
8615                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8616                         "Invalid handle (%s:%u:%u).\n",
8617                         OUR_HANDLE(r->in.handle)));
8618                 return WERR_BADFID;
8619         }
8620
8621         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8622                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8623                         "printer properties change denied by handle\n"));
8624                 return WERR_ACCESS_DENIED;
8625         }
8626
8627         if (!r->in.value_name || !r->in.key_name) {
8628                 return WERR_NOMEM;
8629         }
8630
8631         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8632                 return WERR_BADFID;
8633         }
8634         printer = lp_const_servicename(snum);
8635
8636         status = winreg_delete_printer_dataex(p->mem_ctx,
8637                                               p->server_info,
8638                                               printer,
8639                                               r->in.key_name,
8640                                               r->in.value_name);
8641         if (W_ERROR_IS_OK(status)) {
8642                 status = winreg_printer_update_changeid(p->mem_ctx,
8643                                                         p->server_info,
8644                                                         printer);
8645         }
8646
8647         return status;
8648 }
8649
8650 /****************************************************************
8651  _spoolss_EnumPrinterKey
8652 ****************************************************************/
8653
8654 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8655                                struct spoolss_EnumPrinterKey *r)
8656 {
8657         uint32_t        num_keys;
8658         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8659         int             snum = 0;
8660         WERROR          result = WERR_BADFILE;
8661         const char **array = NULL;
8662         DATA_BLOB blob;
8663
8664         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8665
8666         if (!Printer) {
8667                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8668                         OUR_HANDLE(r->in.handle)));
8669                 return WERR_BADFID;
8670         }
8671
8672         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8673                 return WERR_BADFID;
8674         }
8675
8676         result = winreg_enum_printer_key(p->mem_ctx,
8677                                          p->server_info,
8678                                          lp_const_servicename(snum),
8679                                          r->in.key_name,
8680                                          &num_keys,
8681                                          &array);
8682         if (!W_ERROR_IS_OK(result)) {
8683                 goto done;
8684         }
8685
8686         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8687                 result = WERR_NOMEM;
8688                 goto done;
8689         }
8690
8691         *r->out._ndr_size = r->in.offered / 2;
8692         *r->out.needed = blob.length;
8693
8694         if (r->in.offered < *r->out.needed) {
8695                 result = WERR_MORE_DATA;
8696         } else {
8697                 result = WERR_OK;
8698                 r->out.key_buffer->string_array = array;
8699         }
8700
8701  done:
8702         if (!W_ERROR_IS_OK(result)) {
8703                 TALLOC_FREE(array);
8704                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8705                         *r->out.needed = 0;
8706                 }
8707         }
8708
8709         return result;
8710 }
8711
8712 /****************************************************************
8713  _spoolss_DeletePrinterKey
8714 ****************************************************************/
8715
8716 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8717                                  struct spoolss_DeletePrinterKey *r)
8718 {
8719         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8720         int                     snum=0;
8721         WERROR                  status;
8722         const char *printer;
8723
8724         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8725
8726         if (!Printer) {
8727                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8728                         OUR_HANDLE(r->in.handle)));
8729                 return WERR_BADFID;
8730         }
8731
8732         /* if keyname == NULL, return error */
8733         if ( !r->in.key_name )
8734                 return WERR_INVALID_PARAM;
8735
8736         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8737                 return WERR_BADFID;
8738         }
8739
8740         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8741                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8742                         "printer properties change denied by handle\n"));
8743                 return WERR_ACCESS_DENIED;
8744         }
8745
8746         printer = lp_const_servicename(snum);
8747
8748         /* delete the key and all subkeys */
8749         status = winreg_delete_printer_key(p->mem_ctx,
8750                                            p->server_info,
8751                                            printer,
8752                                            r->in.key_name);
8753         if (W_ERROR_IS_OK(status)) {
8754                 status = winreg_printer_update_changeid(p->mem_ctx,
8755                                                         p->server_info,
8756                                                         printer);
8757         }
8758
8759         return status;
8760 }
8761
8762 /****************************************************************
8763  _spoolss_EnumPrinterDataEx
8764 ****************************************************************/
8765
8766 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8767                                   struct spoolss_EnumPrinterDataEx *r)
8768 {
8769         uint32_t        count = 0;
8770         struct spoolss_PrinterEnumValues *info = NULL;
8771         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8772         int             snum;
8773         WERROR          result;
8774
8775         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8776
8777         *r->out.count = 0;
8778         *r->out.needed = 0;
8779         *r->out.info = NULL;
8780
8781         if (!Printer) {
8782                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8783                         OUR_HANDLE(r->in.handle)));
8784                 return WERR_BADFID;
8785         }
8786
8787         /*
8788          * first check for a keyname of NULL or "".  Win2k seems to send
8789          * this a lot and we should send back WERR_INVALID_PARAM
8790          * no need to spend time looking up the printer in this case.
8791          * --jerry
8792          */
8793
8794         if (!strlen(r->in.key_name)) {
8795                 result = WERR_INVALID_PARAM;
8796                 goto done;
8797         }
8798
8799         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8800                 return WERR_BADFID;
8801         }
8802
8803         /* now look for a match on the key name */
8804         result = winreg_enum_printer_dataex(p->mem_ctx,
8805                                             p->server_info,
8806                                             lp_const_servicename(snum),
8807                                             r->in.key_name,
8808                                             &count,
8809                                             &info);
8810         if (!W_ERROR_IS_OK(result)) {
8811                 goto done;
8812         }
8813
8814 #if 0 /* FIXME - gd */
8815         /* housekeeping information in the reply */
8816
8817         /* Fix from Martin Zielinski <mz@seh.de> - ensure
8818          * the hand marshalled container size is a multiple
8819          * of 4 bytes for RPC alignment.
8820          */
8821
8822         if (needed % 4) {
8823                 needed += 4-(needed % 4);
8824         }
8825 #endif
8826         *r->out.count   = count;
8827         *r->out.info    = info;
8828
8829  done:
8830         if (!W_ERROR_IS_OK(result)) {
8831                 return result;
8832         }
8833
8834         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8835                                                spoolss_EnumPrinterDataEx, 
8836                                                *r->out.info,
8837                                                *r->out.count);
8838         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8839         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8840
8841         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8842 }
8843
8844 /****************************************************************************
8845 ****************************************************************************/
8846
8847 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8848                                                  const char *servername,
8849                                                  const char *environment,
8850                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
8851 {
8852         WERROR werr;
8853         char *path = NULL;
8854
8855         werr = compose_spoolss_server_path(mem_ctx,
8856                                            servername,
8857                                            environment,
8858                                            SPOOLSS_PRTPROCS_PATH,
8859                                            &path);
8860         if (!W_ERROR_IS_OK(werr)) {
8861                 return werr;
8862         }
8863
8864         DEBUG(4,("print processor directory: [%s]\n", path));
8865
8866         r->directory_name = path;
8867
8868         return WERR_OK;
8869 }
8870
8871 /****************************************************************
8872  _spoolss_GetPrintProcessorDirectory
8873 ****************************************************************/
8874
8875 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8876                                            struct spoolss_GetPrintProcessorDirectory *r)
8877 {
8878         WERROR result;
8879
8880         /* that's an [in out] buffer */
8881
8882         if (!r->in.buffer && (r->in.offered != 0)) {
8883                 return WERR_INVALID_PARAM;
8884         }
8885
8886         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8887                 r->in.level));
8888
8889         *r->out.needed = 0;
8890
8891         /* r->in.level is ignored */
8892
8893         /* We always should reply with a local print processor directory so that
8894          * users are not forced to have a [prnproc$] share on the Samba spoolss
8895          * server - Guenther */
8896
8897         result = getprintprocessordirectory_level_1(p->mem_ctx,
8898                                                     NULL, /* r->in.server */
8899                                                     r->in.environment,
8900                                                     &r->out.info->info1);
8901         if (!W_ERROR_IS_OK(result)) {
8902                 TALLOC_FREE(r->out.info);
8903                 return result;
8904         }
8905
8906         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8907                                                                                    r->out.info, r->in.level);
8908         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8909
8910         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8911 }
8912
8913 /*******************************************************************
8914  ********************************************************************/
8915
8916 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8917                                const char *dllname)
8918 {
8919         enum ndr_err_code ndr_err;
8920         struct spoolss_MonitorUi ui;
8921
8922         ui.dll_name = dllname;
8923
8924         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8925                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8926         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8927                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8928         }
8929         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8930 }
8931
8932 /*******************************************************************
8933  Streams the monitor UI DLL name in UNICODE
8934 *******************************************************************/
8935
8936 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8937                                NT_USER_TOKEN *token, DATA_BLOB *in,
8938                                DATA_BLOB *out, uint32_t *needed)
8939 {
8940         const char *dllname = "tcpmonui.dll";
8941
8942         *needed = (strlen(dllname)+1) * 2;
8943
8944         if (out->length < *needed) {
8945                 return WERR_INSUFFICIENT_BUFFER;
8946         }
8947
8948         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8949                 return WERR_NOMEM;
8950         }
8951
8952         return WERR_OK;
8953 }
8954
8955 /*******************************************************************
8956  ********************************************************************/
8957
8958 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
8959                              struct spoolss_PortData1 *port1,
8960                              const DATA_BLOB *buf)
8961 {
8962         enum ndr_err_code ndr_err;
8963         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
8964                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
8965         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8966                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
8967         }
8968         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8969 }
8970
8971 /*******************************************************************
8972  ********************************************************************/
8973
8974 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
8975                              struct spoolss_PortData2 *port2,
8976                              const DATA_BLOB *buf)
8977 {
8978         enum ndr_err_code ndr_err;
8979         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
8980                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
8981         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8982                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
8983         }
8984         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8985 }
8986
8987 /*******************************************************************
8988  Create a new TCP/IP port
8989 *******************************************************************/
8990
8991 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
8992                              NT_USER_TOKEN *token, DATA_BLOB *in,
8993                              DATA_BLOB *out, uint32_t *needed)
8994 {
8995         struct spoolss_PortData1 port1;
8996         struct spoolss_PortData2 port2;
8997         char *device_uri = NULL;
8998         uint32_t version;
8999
9000         const char *portname;
9001         const char *hostaddress;
9002         const char *queue;
9003         uint32_t port_number;
9004         uint32_t protocol;
9005
9006         /* peek for spoolss_PortData version */
9007
9008         if (!in || (in->length < (128 + 4))) {
9009                 return WERR_GENERAL_FAILURE;
9010         }
9011
9012         version = IVAL(in->data, 128);
9013
9014         switch (version) {
9015                 case 1:
9016                         ZERO_STRUCT(port1);
9017
9018                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9019                                 return WERR_NOMEM;
9020                         }
9021
9022                         portname        = port1.portname;
9023                         hostaddress     = port1.hostaddress;
9024                         queue           = port1.queue;
9025                         protocol        = port1.protocol;
9026                         port_number     = port1.port_number;
9027
9028                         break;
9029                 case 2:
9030                         ZERO_STRUCT(port2);
9031
9032                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9033                                 return WERR_NOMEM;
9034                         }
9035
9036                         portname        = port2.portname;
9037                         hostaddress     = port2.hostaddress;
9038                         queue           = port2.queue;
9039                         protocol        = port2.protocol;
9040                         port_number     = port2.port_number;
9041
9042                         break;
9043                 default:
9044                         DEBUG(1,("xcvtcp_addport: "
9045                                 "unknown version of port_data: %d\n", version));
9046                         return WERR_UNKNOWN_PORT;
9047         }
9048
9049         /* create the device URI and call the add_port_hook() */
9050
9051         switch (protocol) {
9052         case PROTOCOL_RAWTCP_TYPE:
9053                 device_uri = talloc_asprintf(mem_ctx,
9054                                 "socket://%s:%d/", hostaddress,
9055                                 port_number);
9056                 break;
9057
9058         case PROTOCOL_LPR_TYPE:
9059                 device_uri = talloc_asprintf(mem_ctx,
9060                         "lpr://%s/%s", hostaddress, queue );
9061                 break;
9062
9063         default:
9064                 return WERR_UNKNOWN_PORT;
9065         }
9066
9067         if (!device_uri) {
9068                 return WERR_NOMEM;
9069         }
9070
9071         return add_port_hook(mem_ctx, token, portname, device_uri);
9072 }
9073
9074 /*******************************************************************
9075 *******************************************************************/
9076
9077 struct xcv_api_table xcvtcp_cmds[] = {
9078         { "MonitorUI",  xcvtcp_monitorui },
9079         { "AddPort",    xcvtcp_addport},
9080         { NULL,         NULL }
9081 };
9082
9083 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9084                                      NT_USER_TOKEN *token, const char *command,
9085                                      DATA_BLOB *inbuf,
9086                                      DATA_BLOB *outbuf,
9087                                      uint32_t *needed )
9088 {
9089         int i;
9090
9091         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9092
9093         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9094                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9095                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9096         }
9097
9098         return WERR_BADFUNC;
9099 }
9100
9101 /*******************************************************************
9102 *******************************************************************/
9103 #if 0   /* don't support management using the "Local Port" monitor */
9104
9105 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9106                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9107                                  DATA_BLOB *out, uint32_t *needed)
9108 {
9109         const char *dllname = "localui.dll";
9110
9111         *needed = (strlen(dllname)+1) * 2;
9112
9113         if (out->length < *needed) {
9114                 return WERR_INSUFFICIENT_BUFFER;
9115         }
9116
9117         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9118                 return WERR_NOMEM;
9119         }
9120
9121         return WERR_OK;
9122 }
9123
9124 /*******************************************************************
9125 *******************************************************************/
9126
9127 struct xcv_api_table xcvlocal_cmds[] = {
9128         { "MonitorUI",  xcvlocal_monitorui },
9129         { NULL,         NULL }
9130 };
9131 #else
9132 struct xcv_api_table xcvlocal_cmds[] = {
9133         { NULL,         NULL }
9134 };
9135 #endif
9136
9137
9138
9139 /*******************************************************************
9140 *******************************************************************/
9141
9142 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9143                                        NT_USER_TOKEN *token, const char *command,
9144                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9145                                        uint32_t *needed)
9146 {
9147         int i;
9148
9149         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9150
9151         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9152                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9153                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9154         }
9155         return WERR_BADFUNC;
9156 }
9157
9158 /****************************************************************
9159  _spoolss_XcvData
9160 ****************************************************************/
9161
9162 WERROR _spoolss_XcvData(pipes_struct *p,
9163                         struct spoolss_XcvData *r)
9164 {
9165         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9166         DATA_BLOB out_data = data_blob_null;
9167         WERROR werror;
9168
9169         if (!Printer) {
9170                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9171                         OUR_HANDLE(r->in.handle)));
9172                 return WERR_BADFID;
9173         }
9174
9175         /* Has to be a handle to the TCP/IP port monitor */
9176
9177         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9178                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9179                 return WERR_BADFID;
9180         }
9181
9182         /* requires administrative access to the server */
9183
9184         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9185                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9186                 return WERR_ACCESS_DENIED;
9187         }
9188
9189         /* Allocate the outgoing buffer */
9190
9191         if (r->in.out_data_size) {
9192                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9193                 if (out_data.data == NULL) {
9194                         return WERR_NOMEM;
9195                 }
9196         }
9197
9198         switch ( Printer->printer_type ) {
9199         case SPLHND_PORTMON_TCP:
9200                 werror = process_xcvtcp_command(p->mem_ctx,
9201                                                 p->server_info->ptok,
9202                                                 r->in.function_name,
9203                                                 &r->in.in_data, &out_data,
9204                                                 r->out.needed);
9205                 break;
9206         case SPLHND_PORTMON_LOCAL:
9207                 werror = process_xcvlocal_command(p->mem_ctx,
9208                                                   p->server_info->ptok,
9209                                                   r->in.function_name,
9210                                                   &r->in.in_data, &out_data,
9211                                                   r->out.needed);
9212                 break;
9213         default:
9214                 werror = WERR_INVALID_PRINT_MONITOR;
9215         }
9216
9217         if (!W_ERROR_IS_OK(werror)) {
9218                 return werror;
9219         }
9220
9221         *r->out.status_code = 0;
9222
9223         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9224                 memcpy(r->out.out_data, out_data.data,
9225                         MIN(r->in.out_data_size, out_data.length));
9226         }
9227
9228         return WERR_OK;
9229 }
9230
9231 /****************************************************************
9232  _spoolss_AddPrintProcessor
9233 ****************************************************************/
9234
9235 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9236                                   struct spoolss_AddPrintProcessor *r)
9237 {
9238         /* for now, just indicate success and ignore the add.  We'll
9239            automatically set the winprint processor for printer
9240            entries later.  Used to debug the LexMark Optra S 1855 PCL
9241            driver --jerry */
9242
9243         return WERR_OK;
9244 }
9245
9246 /****************************************************************
9247  _spoolss_AddPort
9248 ****************************************************************/
9249
9250 WERROR _spoolss_AddPort(pipes_struct *p,
9251                         struct spoolss_AddPort *r)
9252 {
9253         /* do what w2k3 does */
9254
9255         return WERR_NOT_SUPPORTED;
9256 }
9257
9258 /****************************************************************
9259  _spoolss_GetPrinterDriver
9260 ****************************************************************/
9261
9262 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9263                                  struct spoolss_GetPrinterDriver *r)
9264 {
9265         p->rng_fault_state = true;
9266         return WERR_NOT_SUPPORTED;
9267 }
9268
9269 /****************************************************************
9270  _spoolss_ReadPrinter
9271 ****************************************************************/
9272
9273 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9274                             struct spoolss_ReadPrinter *r)
9275 {
9276         p->rng_fault_state = true;
9277         return WERR_NOT_SUPPORTED;
9278 }
9279
9280 /****************************************************************
9281  _spoolss_WaitForPrinterChange
9282 ****************************************************************/
9283
9284 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9285                                      struct spoolss_WaitForPrinterChange *r)
9286 {
9287         p->rng_fault_state = true;
9288         return WERR_NOT_SUPPORTED;
9289 }
9290
9291 /****************************************************************
9292  _spoolss_ConfigurePort
9293 ****************************************************************/
9294
9295 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9296                               struct spoolss_ConfigurePort *r)
9297 {
9298         p->rng_fault_state = true;
9299         return WERR_NOT_SUPPORTED;
9300 }
9301
9302 /****************************************************************
9303  _spoolss_DeletePort
9304 ****************************************************************/
9305
9306 WERROR _spoolss_DeletePort(pipes_struct *p,
9307                            struct spoolss_DeletePort *r)
9308 {
9309         p->rng_fault_state = true;
9310         return WERR_NOT_SUPPORTED;
9311 }
9312
9313 /****************************************************************
9314  _spoolss_CreatePrinterIC
9315 ****************************************************************/
9316
9317 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9318                                 struct spoolss_CreatePrinterIC *r)
9319 {
9320         p->rng_fault_state = true;
9321         return WERR_NOT_SUPPORTED;
9322 }
9323
9324 /****************************************************************
9325  _spoolss_PlayGDIScriptOnPrinterIC
9326 ****************************************************************/
9327
9328 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9329                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9330 {
9331         p->rng_fault_state = true;
9332         return WERR_NOT_SUPPORTED;
9333 }
9334
9335 /****************************************************************
9336  _spoolss_DeletePrinterIC
9337 ****************************************************************/
9338
9339 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9340                                 struct spoolss_DeletePrinterIC *r)
9341 {
9342         p->rng_fault_state = true;
9343         return WERR_NOT_SUPPORTED;
9344 }
9345
9346 /****************************************************************
9347  _spoolss_AddPrinterConnection
9348 ****************************************************************/
9349
9350 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9351                                      struct spoolss_AddPrinterConnection *r)
9352 {
9353         p->rng_fault_state = true;
9354         return WERR_NOT_SUPPORTED;
9355 }
9356
9357 /****************************************************************
9358  _spoolss_DeletePrinterConnection
9359 ****************************************************************/
9360
9361 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9362                                         struct spoolss_DeletePrinterConnection *r)
9363 {
9364         p->rng_fault_state = true;
9365         return WERR_NOT_SUPPORTED;
9366 }
9367
9368 /****************************************************************
9369  _spoolss_PrinterMessageBox
9370 ****************************************************************/
9371
9372 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9373                                   struct spoolss_PrinterMessageBox *r)
9374 {
9375         p->rng_fault_state = true;
9376         return WERR_NOT_SUPPORTED;
9377 }
9378
9379 /****************************************************************
9380  _spoolss_AddMonitor
9381 ****************************************************************/
9382
9383 WERROR _spoolss_AddMonitor(pipes_struct *p,
9384                            struct spoolss_AddMonitor *r)
9385 {
9386         p->rng_fault_state = true;
9387         return WERR_NOT_SUPPORTED;
9388 }
9389
9390 /****************************************************************
9391  _spoolss_DeleteMonitor
9392 ****************************************************************/
9393
9394 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9395                               struct spoolss_DeleteMonitor *r)
9396 {
9397         p->rng_fault_state = true;
9398         return WERR_NOT_SUPPORTED;
9399 }
9400
9401 /****************************************************************
9402  _spoolss_DeletePrintProcessor
9403 ****************************************************************/
9404
9405 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9406                                      struct spoolss_DeletePrintProcessor *r)
9407 {
9408         p->rng_fault_state = true;
9409         return WERR_NOT_SUPPORTED;
9410 }
9411
9412 /****************************************************************
9413  _spoolss_AddPrintProvidor
9414 ****************************************************************/
9415
9416 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9417                                  struct spoolss_AddPrintProvidor *r)
9418 {
9419         p->rng_fault_state = true;
9420         return WERR_NOT_SUPPORTED;
9421 }
9422
9423 /****************************************************************
9424  _spoolss_DeletePrintProvidor
9425 ****************************************************************/
9426
9427 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9428                                     struct spoolss_DeletePrintProvidor *r)
9429 {
9430         p->rng_fault_state = true;
9431         return WERR_NOT_SUPPORTED;
9432 }
9433
9434 /****************************************************************
9435  _spoolss_FindFirstPrinterChangeNotification
9436 ****************************************************************/
9437
9438 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9439                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9440 {
9441         p->rng_fault_state = true;
9442         return WERR_NOT_SUPPORTED;
9443 }
9444
9445 /****************************************************************
9446  _spoolss_FindNextPrinterChangeNotification
9447 ****************************************************************/
9448
9449 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9450                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9451 {
9452         p->rng_fault_state = true;
9453         return WERR_NOT_SUPPORTED;
9454 }
9455
9456 /****************************************************************
9457  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9458 ****************************************************************/
9459
9460 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9461                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9462 {
9463         p->rng_fault_state = true;
9464         return WERR_NOT_SUPPORTED;
9465 }
9466
9467 /****************************************************************
9468  _spoolss_ReplyOpenPrinter
9469 ****************************************************************/
9470
9471 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9472                                  struct spoolss_ReplyOpenPrinter *r)
9473 {
9474         p->rng_fault_state = true;
9475         return WERR_NOT_SUPPORTED;
9476 }
9477
9478 /****************************************************************
9479  _spoolss_RouterReplyPrinter
9480 ****************************************************************/
9481
9482 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9483                                    struct spoolss_RouterReplyPrinter *r)
9484 {
9485         p->rng_fault_state = true;
9486         return WERR_NOT_SUPPORTED;
9487 }
9488
9489 /****************************************************************
9490  _spoolss_ReplyClosePrinter
9491 ****************************************************************/
9492
9493 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9494                                   struct spoolss_ReplyClosePrinter *r)
9495 {
9496         p->rng_fault_state = true;
9497         return WERR_NOT_SUPPORTED;
9498 }
9499
9500 /****************************************************************
9501  _spoolss_AddPortEx
9502 ****************************************************************/
9503
9504 WERROR _spoolss_AddPortEx(pipes_struct *p,
9505                           struct spoolss_AddPortEx *r)
9506 {
9507         p->rng_fault_state = true;
9508         return WERR_NOT_SUPPORTED;
9509 }
9510
9511 /****************************************************************
9512  _spoolss_RouterFindFirstPrinterChangeNotification
9513 ****************************************************************/
9514
9515 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9516                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9517 {
9518         p->rng_fault_state = true;
9519         return WERR_NOT_SUPPORTED;
9520 }
9521
9522 /****************************************************************
9523  _spoolss_SpoolerInit
9524 ****************************************************************/
9525
9526 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9527                             struct spoolss_SpoolerInit *r)
9528 {
9529         p->rng_fault_state = true;
9530         return WERR_NOT_SUPPORTED;
9531 }
9532
9533 /****************************************************************
9534  _spoolss_ResetPrinterEx
9535 ****************************************************************/
9536
9537 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9538                                struct spoolss_ResetPrinterEx *r)
9539 {
9540         p->rng_fault_state = true;
9541         return WERR_NOT_SUPPORTED;
9542 }
9543
9544 /****************************************************************
9545  _spoolss_RouterReplyPrinterEx
9546 ****************************************************************/
9547
9548 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9549                                      struct spoolss_RouterReplyPrinterEx *r)
9550 {
9551         p->rng_fault_state = true;
9552         return WERR_NOT_SUPPORTED;
9553 }
9554
9555 /****************************************************************
9556  _spoolss_44
9557 ****************************************************************/
9558
9559 WERROR _spoolss_44(pipes_struct *p,
9560                    struct spoolss_44 *r)
9561 {
9562         p->rng_fault_state = true;
9563         return WERR_NOT_SUPPORTED;
9564 }
9565
9566 /****************************************************************
9567  _spoolss_47
9568 ****************************************************************/
9569
9570 WERROR _spoolss_47(pipes_struct *p,
9571                    struct spoolss_47 *r)
9572 {
9573         p->rng_fault_state = true;
9574         return WERR_NOT_SUPPORTED;
9575 }
9576
9577 /****************************************************************
9578  _spoolss_4a
9579 ****************************************************************/
9580
9581 WERROR _spoolss_4a(pipes_struct *p,
9582                    struct spoolss_4a *r)
9583 {
9584         p->rng_fault_state = true;
9585         return WERR_NOT_SUPPORTED;
9586 }
9587
9588 /****************************************************************
9589  _spoolss_4b
9590 ****************************************************************/
9591
9592 WERROR _spoolss_4b(pipes_struct *p,
9593                    struct spoolss_4b *r)
9594 {
9595         p->rng_fault_state = true;
9596         return WERR_NOT_SUPPORTED;
9597 }
9598
9599 /****************************************************************
9600  _spoolss_4c
9601 ****************************************************************/
9602
9603 WERROR _spoolss_4c(pipes_struct *p,
9604                    struct spoolss_4c *r)
9605 {
9606         p->rng_fault_state = true;
9607         return WERR_NOT_SUPPORTED;
9608 }
9609
9610 /****************************************************************
9611  _spoolss_53
9612 ****************************************************************/
9613
9614 WERROR _spoolss_53(pipes_struct *p,
9615                    struct spoolss_53 *r)
9616 {
9617         p->rng_fault_state = true;
9618         return WERR_NOT_SUPPORTED;
9619 }
9620
9621 /****************************************************************
9622  _spoolss_55
9623 ****************************************************************/
9624
9625 WERROR _spoolss_55(pipes_struct *p,
9626                    struct spoolss_55 *r)
9627 {
9628         p->rng_fault_state = true;
9629         return WERR_NOT_SUPPORTED;
9630 }
9631
9632 /****************************************************************
9633  _spoolss_56
9634 ****************************************************************/
9635
9636 WERROR _spoolss_56(pipes_struct *p,
9637                    struct spoolss_56 *r)
9638 {
9639         p->rng_fault_state = true;
9640         return WERR_NOT_SUPPORTED;
9641 }
9642
9643 /****************************************************************
9644  _spoolss_57
9645 ****************************************************************/
9646
9647 WERROR _spoolss_57(pipes_struct *p,
9648                    struct spoolss_57 *r)
9649 {
9650         p->rng_fault_state = true;
9651         return WERR_NOT_SUPPORTED;
9652 }
9653
9654 /****************************************************************
9655  _spoolss_5a
9656 ****************************************************************/
9657
9658 WERROR _spoolss_5a(pipes_struct *p,
9659                    struct spoolss_5a *r)
9660 {
9661         p->rng_fault_state = true;
9662         return WERR_NOT_SUPPORTED;
9663 }
9664
9665 /****************************************************************
9666  _spoolss_5b
9667 ****************************************************************/
9668
9669 WERROR _spoolss_5b(pipes_struct *p,
9670                    struct spoolss_5b *r)
9671 {
9672         p->rng_fault_state = true;
9673         return WERR_NOT_SUPPORTED;
9674 }
9675
9676 /****************************************************************
9677  _spoolss_5c
9678 ****************************************************************/
9679
9680 WERROR _spoolss_5c(pipes_struct *p,
9681                    struct spoolss_5c *r)
9682 {
9683         p->rng_fault_state = true;
9684         return WERR_NOT_SUPPORTED;
9685 }
9686
9687 /****************************************************************
9688  _spoolss_5d
9689 ****************************************************************/
9690
9691 WERROR _spoolss_5d(pipes_struct *p,
9692                    struct spoolss_5d *r)
9693 {
9694         p->rng_fault_state = true;
9695         return WERR_NOT_SUPPORTED;
9696 }
9697
9698 /****************************************************************
9699  _spoolss_5e
9700 ****************************************************************/
9701
9702 WERROR _spoolss_5e(pipes_struct *p,
9703                    struct spoolss_5e *r)
9704 {
9705         p->rng_fault_state = true;
9706         return WERR_NOT_SUPPORTED;
9707 }
9708
9709 /****************************************************************
9710  _spoolss_5f
9711 ****************************************************************/
9712
9713 WERROR _spoolss_5f(pipes_struct *p,
9714                    struct spoolss_5f *r)
9715 {
9716         p->rng_fault_state = true;
9717         return WERR_NOT_SUPPORTED;
9718 }
9719
9720 /****************************************************************
9721  _spoolss_60
9722 ****************************************************************/
9723
9724 WERROR _spoolss_60(pipes_struct *p,
9725                    struct spoolss_60 *r)
9726 {
9727         p->rng_fault_state = true;
9728         return WERR_NOT_SUPPORTED;
9729 }
9730
9731 /****************************************************************
9732  _spoolss_61
9733 ****************************************************************/
9734
9735 WERROR _spoolss_61(pipes_struct *p,
9736                    struct spoolss_61 *r)
9737 {
9738         p->rng_fault_state = true;
9739         return WERR_NOT_SUPPORTED;
9740 }
9741
9742 /****************************************************************
9743  _spoolss_62
9744 ****************************************************************/
9745
9746 WERROR _spoolss_62(pipes_struct *p,
9747                    struct spoolss_62 *r)
9748 {
9749         p->rng_fault_state = true;
9750         return WERR_NOT_SUPPORTED;
9751 }
9752
9753 /****************************************************************
9754  _spoolss_63
9755 ****************************************************************/
9756
9757 WERROR _spoolss_63(pipes_struct *p,
9758                    struct spoolss_63 *r)
9759 {
9760         p->rng_fault_state = true;
9761         return WERR_NOT_SUPPORTED;
9762 }
9763
9764 /****************************************************************
9765  _spoolss_64
9766 ****************************************************************/
9767
9768 WERROR _spoolss_64(pipes_struct *p,
9769                    struct spoolss_64 *r)
9770 {
9771         p->rng_fault_state = true;
9772         return WERR_NOT_SUPPORTED;
9773 }
9774
9775 /****************************************************************
9776  _spoolss_65
9777 ****************************************************************/
9778
9779 WERROR _spoolss_65(pipes_struct *p,
9780                    struct spoolss_65 *r)
9781 {
9782         p->rng_fault_state = true;
9783         return WERR_NOT_SUPPORTED;
9784 }
9785
9786 /****************************************************************
9787  _spoolss_GetCorePrinterDrivers
9788 ****************************************************************/
9789
9790 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9791                                       struct spoolss_GetCorePrinterDrivers *r)
9792 {
9793         p->rng_fault_state = true;
9794         return WERR_NOT_SUPPORTED;
9795 }
9796
9797 /****************************************************************
9798  _spoolss_67
9799 ****************************************************************/
9800
9801 WERROR _spoolss_67(pipes_struct *p,
9802                    struct spoolss_67 *r)
9803 {
9804         p->rng_fault_state = true;
9805         return WERR_NOT_SUPPORTED;
9806 }
9807
9808 /****************************************************************
9809  _spoolss_GetPrinterDriverPackagePath
9810 ****************************************************************/
9811
9812 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9813                                             struct spoolss_GetPrinterDriverPackagePath *r)
9814 {
9815         p->rng_fault_state = true;
9816         return WERR_NOT_SUPPORTED;
9817 }
9818
9819 /****************************************************************
9820  _spoolss_69
9821 ****************************************************************/
9822
9823 WERROR _spoolss_69(pipes_struct *p,
9824                    struct spoolss_69 *r)
9825 {
9826         p->rng_fault_state = true;
9827         return WERR_NOT_SUPPORTED;
9828 }
9829
9830 /****************************************************************
9831  _spoolss_6a
9832 ****************************************************************/
9833
9834 WERROR _spoolss_6a(pipes_struct *p,
9835                    struct spoolss_6a *r)
9836 {
9837         p->rng_fault_state = true;
9838         return WERR_NOT_SUPPORTED;
9839 }
9840
9841 /****************************************************************
9842  _spoolss_6b
9843 ****************************************************************/
9844
9845 WERROR _spoolss_6b(pipes_struct *p,
9846                    struct spoolss_6b *r)
9847 {
9848         p->rng_fault_state = true;
9849         return WERR_NOT_SUPPORTED;
9850 }
9851
9852 /****************************************************************
9853  _spoolss_6c
9854 ****************************************************************/
9855
9856 WERROR _spoolss_6c(pipes_struct *p,
9857                    struct spoolss_6c *r)
9858 {
9859         p->rng_fault_state = true;
9860         return WERR_NOT_SUPPORTED;
9861 }
9862
9863 /****************************************************************
9864  _spoolss_6d
9865 ****************************************************************/
9866
9867 WERROR _spoolss_6d(pipes_struct *p,
9868                    struct spoolss_6d *r)
9869 {
9870         p->rng_fault_state = true;
9871         return WERR_NOT_SUPPORTED;
9872 }