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