s3-spoolss: Migrated spoolss_EnumForms 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         nt_forms_struct tmpForm;
7654         int snum = -1;
7655         WERROR status = WERR_OK;
7656         NT_PRINTER_INFO_LEVEL *printer = NULL;
7657         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7658
7659         int count=0;
7660         nt_forms_struct *list=NULL;
7661         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7662         int i;
7663
7664         DEBUG(5,("_spoolss_AddForm\n"));
7665
7666         if (!Printer) {
7667                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7668                         OUR_HANDLE(r->in.handle)));
7669                 return WERR_BADFID;
7670         }
7671
7672
7673         /* forms can be added on printer or on the print server handle */
7674
7675         if ( Printer->printer_type == SPLHND_PRINTER )
7676         {
7677                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7678                         return WERR_BADFID;
7679
7680                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7681                 if (!W_ERROR_IS_OK(status))
7682                         goto done;
7683         }
7684
7685         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7686            and not a printer admin, then fail */
7687
7688         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7689              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7690              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7691                                           p->server_info->info3->base.domain.string,
7692                                           NULL,
7693                                           p->server_info->ptok,
7694                                           lp_printer_admin(snum))) {
7695                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7696                 status = WERR_ACCESS_DENIED;
7697                 goto done;
7698         }
7699
7700         switch (form->flags) {
7701         case SPOOLSS_FORM_USER:
7702         case SPOOLSS_FORM_BUILTIN:
7703         case SPOOLSS_FORM_PRINTER:
7704                 break;
7705         default:
7706                 status = WERR_INVALID_PARAM;
7707                 goto done;
7708         }
7709
7710         /* can't add if builtin */
7711
7712         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7713                 status = WERR_FILE_EXISTS;
7714                 goto done;
7715         }
7716
7717         count = get_ntforms(&list);
7718
7719         for (i=0; i < count; i++) {
7720                 if (strequal(form->form_name, list[i].name)) {
7721                         status = WERR_FILE_EXISTS;
7722                         goto done;
7723                 }
7724         }
7725
7726         if(!add_a_form(&list, form, &count)) {
7727                 status =  WERR_NOMEM;
7728                 goto done;
7729         }
7730
7731         become_root();
7732         write_ntforms(&list, count);
7733         unbecome_root();
7734
7735         /*
7736          * ChangeID must always be set if this is a printer
7737          */
7738
7739         if ( Printer->printer_type == SPLHND_PRINTER )
7740                 status = mod_a_printer(printer, 2);
7741
7742 done:
7743         if ( printer )
7744                 free_a_printer(&printer, 2);
7745         SAFE_FREE(list);
7746
7747         return status;
7748 }
7749
7750 /****************************************************************
7751  _spoolss_DeleteForm
7752 ****************************************************************/
7753
7754 WERROR _spoolss_DeleteForm(pipes_struct *p,
7755                            struct spoolss_DeleteForm *r)
7756 {
7757         const char *form_name = r->in.form_name;
7758         nt_forms_struct tmpForm;
7759         int count=0;
7760         nt_forms_struct *list=NULL;
7761         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7762         int snum = -1;
7763         WERROR status = WERR_OK;
7764         NT_PRINTER_INFO_LEVEL *printer = NULL;
7765         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7766         bool ret = false;
7767
7768         DEBUG(5,("_spoolss_DeleteForm\n"));
7769
7770         if (!Printer) {
7771                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7772                         OUR_HANDLE(r->in.handle)));
7773                 return WERR_BADFID;
7774         }
7775
7776         /* forms can be deleted on printer of on the print server handle */
7777
7778         if ( Printer->printer_type == SPLHND_PRINTER )
7779         {
7780                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7781                         return WERR_BADFID;
7782
7783                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7784                 if (!W_ERROR_IS_OK(status))
7785                         goto done;
7786         }
7787
7788         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7789              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7790              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7791                                           p->server_info->info3->base.domain.string,
7792                                           NULL,
7793                                           p->server_info->ptok,
7794                                           lp_printer_admin(snum))) {
7795                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7796                 return WERR_ACCESS_DENIED;
7797         }
7798
7799
7800         /* can't delete if builtin */
7801
7802         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7803                 status = WERR_INVALID_PARAM;
7804                 goto done;
7805         }
7806
7807         count = get_ntforms(&list);
7808
7809         become_root();
7810         ret = delete_a_form(&list, form_name, &count, &status);
7811         unbecome_root();
7812         if (ret == false) {
7813                 goto done;
7814         }
7815
7816         /*
7817          * ChangeID must always be set if this is a printer
7818          */
7819
7820         if ( Printer->printer_type == SPLHND_PRINTER )
7821                 status = mod_a_printer(printer, 2);
7822
7823 done:
7824         if ( printer )
7825                 free_a_printer(&printer, 2);
7826         SAFE_FREE(list);
7827
7828         return status;
7829 }
7830
7831 /****************************************************************
7832  _spoolss_SetForm
7833 ****************************************************************/
7834
7835 WERROR _spoolss_SetForm(pipes_struct *p,
7836                         struct spoolss_SetForm *r)
7837 {
7838         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7839         nt_forms_struct tmpForm;
7840         int snum = -1;
7841         WERROR status = WERR_OK;
7842         NT_PRINTER_INFO_LEVEL *printer = NULL;
7843         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7844
7845         int count=0;
7846         nt_forms_struct *list=NULL;
7847         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7848
7849         DEBUG(5,("_spoolss_SetForm\n"));
7850
7851         if (!Printer) {
7852                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7853                         OUR_HANDLE(r->in.handle)));
7854                 return WERR_BADFID;
7855         }
7856
7857         /* forms can be modified on printer of on the print server handle */
7858
7859         if ( Printer->printer_type == SPLHND_PRINTER )
7860         {
7861                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7862                         return WERR_BADFID;
7863
7864                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7865                 if (!W_ERROR_IS_OK(status))
7866                         goto done;
7867         }
7868
7869         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7870            and not a printer admin, then fail */
7871
7872         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7873              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7874              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7875                                           p->server_info->info3->base.domain.string,
7876                                           NULL,
7877                                           p->server_info->ptok,
7878                                           lp_printer_admin(snum))) {
7879                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7880                 status = WERR_ACCESS_DENIED;
7881                 goto done;
7882         }
7883
7884         /* can't set if builtin */
7885         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7886                 status = WERR_INVALID_PARAM;
7887                 goto done;
7888         }
7889
7890         count = get_ntforms(&list);
7891         update_a_form(&list, form, count);
7892         become_root();
7893         write_ntforms(&list, count);
7894         unbecome_root();
7895
7896         /*
7897          * ChangeID must always be set if this is a printer
7898          */
7899
7900         if ( Printer->printer_type == SPLHND_PRINTER )
7901                 status = mod_a_printer(printer, 2);
7902
7903
7904 done:
7905         if ( printer )
7906                 free_a_printer(&printer, 2);
7907         SAFE_FREE(list);
7908
7909         return status;
7910 }
7911
7912 /****************************************************************************
7913  fill_print_processor1
7914 ****************************************************************************/
7915
7916 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7917                                     struct spoolss_PrintProcessorInfo1 *r,
7918                                     const char *print_processor_name)
7919 {
7920         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7921         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7922
7923         return WERR_OK;
7924 }
7925
7926 /****************************************************************************
7927  enumprintprocessors level 1.
7928 ****************************************************************************/
7929
7930 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7931                                           union spoolss_PrintProcessorInfo **info_p,
7932                                           uint32_t *count)
7933 {
7934         union spoolss_PrintProcessorInfo *info;
7935         WERROR result;
7936
7937         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7938         W_ERROR_HAVE_NO_MEMORY(info);
7939
7940         *count = 1;
7941
7942         result = fill_print_processor1(info, &info[0].info1, "winprint");
7943         if (!W_ERROR_IS_OK(result)) {
7944                 goto out;
7945         }
7946
7947  out:
7948         if (!W_ERROR_IS_OK(result)) {
7949                 TALLOC_FREE(info);
7950                 *count = 0;
7951                 return result;
7952         }
7953
7954         *info_p = info;
7955
7956         return WERR_OK;
7957 }
7958
7959 /****************************************************************
7960  _spoolss_EnumPrintProcessors
7961 ****************************************************************/
7962
7963 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7964                                     struct spoolss_EnumPrintProcessors *r)
7965 {
7966         WERROR result;
7967
7968         /* that's an [in out] buffer */
7969
7970         if (!r->in.buffer && (r->in.offered != 0)) {
7971                 return WERR_INVALID_PARAM;
7972         }
7973
7974         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7975
7976         /*
7977          * Enumerate the print processors ...
7978          *
7979          * Just reply with "winprint", to keep NT happy
7980          * and I can use my nice printer checker.
7981          */
7982
7983         *r->out.count = 0;
7984         *r->out.needed = 0;
7985         *r->out.info = NULL;
7986
7987         switch (r->in.level) {
7988         case 1:
7989                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7990                                                      r->out.count);
7991                 break;
7992         default:
7993                 return WERR_UNKNOWN_LEVEL;
7994         }
7995
7996         if (!W_ERROR_IS_OK(result)) {
7997                 return result;
7998         }
7999
8000         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8001                                                      spoolss_EnumPrintProcessors,
8002                                                      *r->out.info, r->in.level,
8003                                                      *r->out.count);
8004         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8005         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8006
8007         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8008 }
8009
8010 /****************************************************************************
8011  fill_printprocdatatype1
8012 ****************************************************************************/
8013
8014 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8015                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8016                                       const char *name_array)
8017 {
8018         r->name_array = talloc_strdup(mem_ctx, name_array);
8019         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8020
8021         return WERR_OK;
8022 }
8023
8024 /****************************************************************************
8025  enumprintprocdatatypes level 1.
8026 ****************************************************************************/
8027
8028 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8029                                              union spoolss_PrintProcDataTypesInfo **info_p,
8030                                              uint32_t *count)
8031 {
8032         WERROR result;
8033         union spoolss_PrintProcDataTypesInfo *info;
8034
8035         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8036         W_ERROR_HAVE_NO_MEMORY(info);
8037
8038         *count = 1;
8039
8040         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8041         if (!W_ERROR_IS_OK(result)) {
8042                 goto out;
8043         }
8044
8045  out:
8046         if (!W_ERROR_IS_OK(result)) {
8047                 TALLOC_FREE(info);
8048                 *count = 0;
8049                 return result;
8050         }
8051
8052         *info_p = info;
8053
8054         return WERR_OK;
8055 }
8056
8057 /****************************************************************
8058  _spoolss_EnumPrintProcDataTypes
8059 ****************************************************************/
8060
8061 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8062                                        struct spoolss_EnumPrintProcDataTypes *r)
8063 {
8064         WERROR result;
8065
8066         /* that's an [in out] buffer */
8067
8068         if (!r->in.buffer && (r->in.offered != 0)) {
8069                 return WERR_INVALID_PARAM;
8070         }
8071
8072         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8073
8074         *r->out.count = 0;
8075         *r->out.needed = 0;
8076         *r->out.info = NULL;
8077
8078         switch (r->in.level) {
8079         case 1:
8080                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8081                                                         r->out.count);
8082                 break;
8083         default:
8084                 return WERR_UNKNOWN_LEVEL;
8085         }
8086
8087         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8088                                                      spoolss_EnumPrintProcDataTypes, 
8089                                                      *r->out.info, r->in.level,
8090                                                      *r->out.count);
8091         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8092         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8093
8094         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8095 }
8096
8097 /****************************************************************************
8098  fill_monitor_1
8099 ****************************************************************************/
8100
8101 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8102                              struct spoolss_MonitorInfo1 *r,
8103                              const char *monitor_name)
8104 {
8105         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8106         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8107
8108         return WERR_OK;
8109 }
8110
8111 /****************************************************************************
8112  fill_monitor_2
8113 ****************************************************************************/
8114
8115 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8116                              struct spoolss_MonitorInfo2 *r,
8117                              const char *monitor_name,
8118                              const char *environment,
8119                              const char *dll_name)
8120 {
8121         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8122         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8123         r->environment                  = talloc_strdup(mem_ctx, environment);
8124         W_ERROR_HAVE_NO_MEMORY(r->environment);
8125         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8126         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8127
8128         return WERR_OK;
8129 }
8130
8131 /****************************************************************************
8132  enumprintmonitors level 1.
8133 ****************************************************************************/
8134
8135 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8136                                         union spoolss_MonitorInfo **info_p,
8137                                         uint32_t *count)
8138 {
8139         union spoolss_MonitorInfo *info;
8140         WERROR result = WERR_OK;
8141
8142         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8143         W_ERROR_HAVE_NO_MEMORY(info);
8144
8145         *count = 2;
8146
8147         result = fill_monitor_1(info, &info[0].info1,
8148                                 SPL_LOCAL_PORT);
8149         if (!W_ERROR_IS_OK(result)) {
8150                 goto out;
8151         }
8152
8153         result = fill_monitor_1(info, &info[1].info1,
8154                                 SPL_TCPIP_PORT);
8155         if (!W_ERROR_IS_OK(result)) {
8156                 goto out;
8157         }
8158
8159 out:
8160         if (!W_ERROR_IS_OK(result)) {
8161                 TALLOC_FREE(info);
8162                 *count = 0;
8163                 return result;
8164         }
8165
8166         *info_p = info;
8167
8168         return WERR_OK;
8169 }
8170
8171 /****************************************************************************
8172  enumprintmonitors level 2.
8173 ****************************************************************************/
8174
8175 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8176                                         union spoolss_MonitorInfo **info_p,
8177                                         uint32_t *count)
8178 {
8179         union spoolss_MonitorInfo *info;
8180         WERROR result = WERR_OK;
8181
8182         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8183         W_ERROR_HAVE_NO_MEMORY(info);
8184
8185         *count = 2;
8186
8187         result = fill_monitor_2(info, &info[0].info2,
8188                                 SPL_LOCAL_PORT,
8189                                 "Windows NT X86", /* FIXME */
8190                                 "localmon.dll");
8191         if (!W_ERROR_IS_OK(result)) {
8192                 goto out;
8193         }
8194
8195         result = fill_monitor_2(info, &info[1].info2,
8196                                 SPL_TCPIP_PORT,
8197                                 "Windows NT X86", /* FIXME */
8198                                 "tcpmon.dll");
8199         if (!W_ERROR_IS_OK(result)) {
8200                 goto out;
8201         }
8202
8203 out:
8204         if (!W_ERROR_IS_OK(result)) {
8205                 TALLOC_FREE(info);
8206                 *count = 0;
8207                 return result;
8208         }
8209
8210         *info_p = info;
8211
8212         return WERR_OK;
8213 }
8214
8215 /****************************************************************
8216  _spoolss_EnumMonitors
8217 ****************************************************************/
8218
8219 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8220                              struct spoolss_EnumMonitors *r)
8221 {
8222         WERROR result;
8223
8224         /* that's an [in out] buffer */
8225
8226         if (!r->in.buffer && (r->in.offered != 0)) {
8227                 return WERR_INVALID_PARAM;
8228         }
8229
8230         DEBUG(5,("_spoolss_EnumMonitors\n"));
8231
8232         /*
8233          * Enumerate the print monitors ...
8234          *
8235          * Just reply with "Local Port", to keep NT happy
8236          * and I can use my nice printer checker.
8237          */
8238
8239         *r->out.count = 0;
8240         *r->out.needed = 0;
8241         *r->out.info = NULL;
8242
8243         switch (r->in.level) {
8244         case 1:
8245                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8246                                                    r->out.count);
8247                 break;
8248         case 2:
8249                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8250                                                    r->out.count);
8251                 break;
8252         default:
8253                 return WERR_UNKNOWN_LEVEL;
8254         }
8255
8256         if (!W_ERROR_IS_OK(result)) {
8257                 return result;
8258         }
8259
8260         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8261                                                      spoolss_EnumMonitors, 
8262                                                      *r->out.info, r->in.level,
8263                                                      *r->out.count);
8264         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8265         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8266
8267         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8268 }
8269
8270 /****************************************************************************
8271 ****************************************************************************/
8272
8273 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8274                              const print_queue_struct *queue,
8275                              int count, int snum,
8276                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8277                              uint32_t jobid,
8278                              struct spoolss_JobInfo1 *r)
8279 {
8280         int i = 0;
8281         bool found = false;
8282
8283         for (i=0; i<count; i++) {
8284                 if (queue[i].job == (int)jobid) {
8285                         found = true;
8286                         break;
8287                 }
8288         }
8289
8290         if (found == false) {
8291                 /* NT treats not found as bad param... yet another bad choice */
8292                 return WERR_INVALID_PARAM;
8293         }
8294
8295         return fill_job_info1(mem_ctx,
8296                               r,
8297                               &queue[i],
8298                               i,
8299                               snum,
8300                               ntprinter);
8301 }
8302
8303 /****************************************************************************
8304 ****************************************************************************/
8305
8306 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8307                              const print_queue_struct *queue,
8308                              int count, int snum,
8309                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8310                              uint32_t jobid,
8311                              struct spoolss_JobInfo2 *r)
8312 {
8313         int i = 0;
8314         bool found = false;
8315         struct spoolss_DeviceMode *devmode;
8316
8317         for (i=0; i<count; i++) {
8318                 if (queue[i].job == (int)jobid) {
8319                         found = true;
8320                         break;
8321                 }
8322         }
8323
8324         if (found == false) {
8325                 /* NT treats not found as bad param... yet another bad
8326                    choice */
8327                 return WERR_INVALID_PARAM;
8328         }
8329
8330         /*
8331          * if the print job does not have a DEVMODE associated with it,
8332          * just use the one for the printer. A NULL devicemode is not
8333          *  a failure condition
8334          */
8335
8336         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8337         if (!devmode) {
8338                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8339                 W_ERROR_HAVE_NO_MEMORY(devmode);
8340         }
8341
8342         return fill_job_info2(mem_ctx,
8343                               r,
8344                               &queue[i],
8345                               i,
8346                               snum,
8347                               ntprinter,
8348                               devmode);
8349 }
8350
8351 /****************************************************************
8352  _spoolss_GetJob
8353 ****************************************************************/
8354
8355 WERROR _spoolss_GetJob(pipes_struct *p,
8356                        struct spoolss_GetJob *r)
8357 {
8358         WERROR result = WERR_OK;
8359         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8360         int snum;
8361         int count;
8362         print_queue_struct      *queue = NULL;
8363         print_status_struct prt_status;
8364
8365         /* that's an [in out] buffer */
8366
8367         if (!r->in.buffer && (r->in.offered != 0)) {
8368                 return WERR_INVALID_PARAM;
8369         }
8370
8371         DEBUG(5,("_spoolss_GetJob\n"));
8372
8373         *r->out.needed = 0;
8374
8375         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8376                 return WERR_BADFID;
8377         }
8378
8379         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8380         if (!W_ERROR_IS_OK(result)) {
8381                 return result;
8382         }
8383
8384         count = print_queue_status(snum, &queue, &prt_status);
8385
8386         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8387                      count, prt_status.status, prt_status.message));
8388
8389         switch (r->in.level) {
8390         case 1:
8391                 result = getjob_level_1(p->mem_ctx,
8392                                         queue, count, snum, ntprinter,
8393                                         r->in.job_id, &r->out.info->info1);
8394                 break;
8395         case 2:
8396                 result = getjob_level_2(p->mem_ctx,
8397                                         queue, count, snum, ntprinter,
8398                                         r->in.job_id, &r->out.info->info2);
8399                 break;
8400         default:
8401                 result = WERR_UNKNOWN_LEVEL;
8402                 break;
8403         }
8404
8405         SAFE_FREE(queue);
8406         free_a_printer(&ntprinter, 2);
8407
8408         if (!W_ERROR_IS_OK(result)) {
8409                 TALLOC_FREE(r->out.info);
8410                 return result;
8411         }
8412
8413         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8414                                                                                    r->in.level);
8415         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8416
8417         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8418 }
8419
8420 /****************************************************************
8421  _spoolss_GetPrinterDataEx
8422 ****************************************************************/
8423
8424 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8425                                  struct spoolss_GetPrinterDataEx *r)
8426 {
8427
8428         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8429         const char *printer;
8430         int                     snum = 0;
8431         WERROR result = WERR_OK;
8432         DATA_BLOB blob;
8433         enum winreg_Type val_type;
8434         uint8_t *val_data;
8435         uint32_t val_size;
8436
8437
8438         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8439
8440         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8441                 r->in.key_name, r->in.value_name));
8442
8443         /* in case of problem, return some default values */
8444
8445         *r->out.needed  = 0;
8446         *r->out.type    = REG_NONE;
8447
8448         if (!Printer) {
8449                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8450                         OUR_HANDLE(r->in.handle)));
8451                 result = WERR_BADFID;
8452                 goto done;
8453         }
8454
8455         /* Is the handle to a printer or to the server? */
8456
8457         if (Printer->printer_type == SPLHND_SERVER) {
8458
8459                 union spoolss_PrinterData data;
8460
8461                 result = getprinterdata_printer_server(p->mem_ctx,
8462                                                        r->in.value_name,
8463                                                        r->out.type,
8464                                                        &data);
8465                 if (!W_ERROR_IS_OK(result)) {
8466                         return result;
8467                 }
8468
8469                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8470                                                   *r->out.type, &data);
8471                 if (!W_ERROR_IS_OK(result)) {
8472                         return result;
8473                 }
8474
8475                 *r->out.needed = blob.length;
8476
8477                 if (r->in.offered >= *r->out.needed) {
8478                         memcpy(r->out.data, blob.data, blob.length);
8479                 }
8480
8481                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8482         }
8483
8484         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8485                 return WERR_BADFID;
8486         }
8487         printer = lp_const_servicename(snum);
8488
8489         /* check to see if the keyname is valid */
8490         if (!strlen(r->in.key_name)) {
8491                 return WERR_INVALID_PARAM;
8492         }
8493
8494         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8495         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8496             strequal(r->in.value_name, "ChangeId")) {
8497                 *r->out.type = REG_DWORD;
8498                 *r->out.needed = 4;
8499                 if (r->in.offered >= *r->out.needed) {
8500                         uint32_t changeid = 0;
8501
8502                         result = winreg_printer_get_changeid(p->mem_ctx,
8503                                                              p->server_info,
8504                                                              printer,
8505                                                              &changeid);
8506                         if (!W_ERROR_IS_OK(result)) {
8507                                 return result;
8508                         }
8509
8510                         SIVAL(r->out.data, 0, changeid);
8511                         result = WERR_OK;
8512                 }
8513                 goto done;
8514         }
8515
8516         result = winreg_get_printer_dataex(p->mem_ctx,
8517                                            p->server_info,
8518                                            printer,
8519                                            r->in.key_name,
8520                                            r->in.value_name,
8521                                            &val_type,
8522                                            &val_data,
8523                                            &val_size);
8524         if (!W_ERROR_IS_OK(result)) {
8525                 return result;
8526         }
8527
8528         *r->out.needed = val_size;
8529         *r->out.type = val_type;
8530
8531         if (r->in.offered >= *r->out.needed) {
8532                 memcpy(r->out.data, val_data, val_size);
8533         }
8534
8535  done:
8536         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8537         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8538
8539         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8540 }
8541
8542 /****************************************************************
8543  _spoolss_SetPrinterDataEx
8544 ****************************************************************/
8545
8546 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8547                                  struct spoolss_SetPrinterDataEx *r)
8548 {
8549         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8550         int                     snum = 0;
8551         WERROR                  result = WERR_OK;
8552         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8553         char                    *oid_string;
8554
8555         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8556
8557         /* From MSDN documentation of SetPrinterDataEx: pass request to
8558            SetPrinterData if key is "PrinterDriverData" */
8559
8560         if (!Printer) {
8561                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8562                         OUR_HANDLE(r->in.handle)));
8563                 return WERR_BADFID;
8564         }
8565
8566         if (Printer->printer_type == SPLHND_SERVER) {
8567                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8568                         "Not implemented for server handles yet\n"));
8569                 return WERR_INVALID_PARAM;
8570         }
8571
8572         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8573                 return WERR_BADFID;
8574         }
8575
8576         /*
8577          * Access check : NT returns "access denied" if you make a
8578          * SetPrinterData call without the necessary privildge.
8579          * we were originally returning OK if nothing changed
8580          * which made Win2k issue **a lot** of SetPrinterData
8581          * when connecting to a printer  --jerry
8582          */
8583
8584         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8585                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8586                         "change denied by handle access permissions\n"));
8587                 return WERR_ACCESS_DENIED;
8588         }
8589
8590         result = winreg_get_printer(Printer, p->server_info,
8591                                     Printer->servername,
8592                                     lp_servicename(snum),
8593                                     &pinfo2);
8594         if (!W_ERROR_IS_OK(result)) {
8595                 return result;
8596         }
8597
8598         /* check for OID in valuename */
8599
8600         oid_string = strchr(r->in.value_name, ',');
8601         if (oid_string) {
8602                 *oid_string = '\0';
8603                 oid_string++;
8604         }
8605
8606         /* save the registry data */
8607
8608         result = winreg_set_printer_dataex(p->mem_ctx,
8609                                            p->server_info,
8610                                            pinfo2->sharename,
8611                                            r->in.key_name,
8612                                            r->in.value_name,
8613                                            r->in.type,
8614                                            r->in.data,
8615                                            r->in.offered);
8616
8617         if (W_ERROR_IS_OK(result)) {
8618                 /* save the OID if one was specified */
8619                 if (oid_string) {
8620                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8621                                 r->in.key_name, SPOOL_OID_KEY);
8622                         if (!str) {
8623                                 result = WERR_NOMEM;
8624                                 goto done;
8625                         }
8626
8627                         /*
8628                          * I'm not checking the status here on purpose.  Don't know
8629                          * if this is right, but I'm returning the status from the
8630                          * previous set_printer_dataex() call.  I have no idea if
8631                          * this is right.    --jerry
8632                          */
8633                         winreg_set_printer_dataex(p->mem_ctx,
8634                                                   p->server_info,
8635                                                   pinfo2->sharename,
8636                                                   str,
8637                                                   r->in.value_name,
8638                                                   REG_SZ,
8639                                                   (uint8_t *) oid_string,
8640                                                   strlen(oid_string) + 1);
8641                 }
8642
8643                 result = winreg_printer_update_changeid(p->mem_ctx,
8644                                                         p->server_info,
8645                                                         lp_const_servicename(snum));
8646
8647         }
8648
8649 done:
8650         talloc_free(pinfo2);
8651         return result;
8652 }
8653
8654 /****************************************************************
8655  _spoolss_DeletePrinterDataEx
8656 ****************************************************************/
8657
8658 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8659                                     struct spoolss_DeletePrinterDataEx *r)
8660 {
8661         const char *printer;
8662         int             snum=0;
8663         WERROR          status = WERR_OK;
8664         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8665
8666         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8667
8668         if (!Printer) {
8669                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8670                         "Invalid handle (%s:%u:%u).\n",
8671                         OUR_HANDLE(r->in.handle)));
8672                 return WERR_BADFID;
8673         }
8674
8675         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8676                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8677                         "printer properties change denied by handle\n"));
8678                 return WERR_ACCESS_DENIED;
8679         }
8680
8681         if (!r->in.value_name || !r->in.key_name) {
8682                 return WERR_NOMEM;
8683         }
8684
8685         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8686                 return WERR_BADFID;
8687         }
8688         printer = lp_const_servicename(snum);
8689
8690         status = winreg_delete_printer_dataex(p->mem_ctx,
8691                                               p->server_info,
8692                                               printer,
8693                                               r->in.key_name,
8694                                               r->in.value_name);
8695         if (W_ERROR_IS_OK(status)) {
8696                 status = winreg_printer_update_changeid(p->mem_ctx,
8697                                                         p->server_info,
8698                                                         printer);
8699         }
8700
8701         return status;
8702 }
8703
8704 /****************************************************************
8705  _spoolss_EnumPrinterKey
8706 ****************************************************************/
8707
8708 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8709                                struct spoolss_EnumPrinterKey *r)
8710 {
8711         uint32_t        num_keys;
8712         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8713         int             snum = 0;
8714         WERROR          result = WERR_BADFILE;
8715         const char **array = NULL;
8716         DATA_BLOB blob;
8717
8718         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8719
8720         if (!Printer) {
8721                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8722                         OUR_HANDLE(r->in.handle)));
8723                 return WERR_BADFID;
8724         }
8725
8726         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8727                 return WERR_BADFID;
8728         }
8729
8730         result = winreg_enum_printer_key(p->mem_ctx,
8731                                          p->server_info,
8732                                          lp_const_servicename(snum),
8733                                          r->in.key_name,
8734                                          &num_keys,
8735                                          &array);
8736         if (!W_ERROR_IS_OK(result)) {
8737                 goto done;
8738         }
8739
8740         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8741                 result = WERR_NOMEM;
8742                 goto done;
8743         }
8744
8745         *r->out._ndr_size = r->in.offered / 2;
8746         *r->out.needed = blob.length;
8747
8748         if (r->in.offered < *r->out.needed) {
8749                 result = WERR_MORE_DATA;
8750         } else {
8751                 result = WERR_OK;
8752                 r->out.key_buffer->string_array = array;
8753         }
8754
8755  done:
8756         if (!W_ERROR_IS_OK(result)) {
8757                 TALLOC_FREE(array);
8758                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8759                         *r->out.needed = 0;
8760                 }
8761         }
8762
8763         return result;
8764 }
8765
8766 /****************************************************************
8767  _spoolss_DeletePrinterKey
8768 ****************************************************************/
8769
8770 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8771                                  struct spoolss_DeletePrinterKey *r)
8772 {
8773         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8774         int                     snum=0;
8775         WERROR                  status;
8776         const char *printer;
8777
8778         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8779
8780         if (!Printer) {
8781                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8782                         OUR_HANDLE(r->in.handle)));
8783                 return WERR_BADFID;
8784         }
8785
8786         /* if keyname == NULL, return error */
8787         if ( !r->in.key_name )
8788                 return WERR_INVALID_PARAM;
8789
8790         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8791                 return WERR_BADFID;
8792         }
8793
8794         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8795                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8796                         "printer properties change denied by handle\n"));
8797                 return WERR_ACCESS_DENIED;
8798         }
8799
8800         printer = lp_const_servicename(snum);
8801
8802         /* delete the key and all subkeys */
8803         status = winreg_delete_printer_key(p->mem_ctx,
8804                                            p->server_info,
8805                                            printer,
8806                                            r->in.key_name);
8807         if (W_ERROR_IS_OK(status)) {
8808                 status = winreg_printer_update_changeid(p->mem_ctx,
8809                                                         p->server_info,
8810                                                         printer);
8811         }
8812
8813         return status;
8814 }
8815
8816 /****************************************************************
8817  _spoolss_EnumPrinterDataEx
8818 ****************************************************************/
8819
8820 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8821                                   struct spoolss_EnumPrinterDataEx *r)
8822 {
8823         uint32_t        count = 0;
8824         struct spoolss_PrinterEnumValues *info = NULL;
8825         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8826         int             snum;
8827         WERROR          result;
8828
8829         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8830
8831         *r->out.count = 0;
8832         *r->out.needed = 0;
8833         *r->out.info = NULL;
8834
8835         if (!Printer) {
8836                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8837                         OUR_HANDLE(r->in.handle)));
8838                 return WERR_BADFID;
8839         }
8840
8841         /*
8842          * first check for a keyname of NULL or "".  Win2k seems to send
8843          * this a lot and we should send back WERR_INVALID_PARAM
8844          * no need to spend time looking up the printer in this case.
8845          * --jerry
8846          */
8847
8848         if (!strlen(r->in.key_name)) {
8849                 result = WERR_INVALID_PARAM;
8850                 goto done;
8851         }
8852
8853         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8854                 return WERR_BADFID;
8855         }
8856
8857         /* now look for a match on the key name */
8858         result = winreg_enum_printer_dataex(p->mem_ctx,
8859                                             p->server_info,
8860                                             lp_const_servicename(snum),
8861                                             r->in.key_name,
8862                                             &count,
8863                                             &info);
8864         if (!W_ERROR_IS_OK(result)) {
8865                 goto done;
8866         }
8867
8868 #if 0 /* FIXME - gd */
8869         /* housekeeping information in the reply */
8870
8871         /* Fix from Martin Zielinski <mz@seh.de> - ensure
8872          * the hand marshalled container size is a multiple
8873          * of 4 bytes for RPC alignment.
8874          */
8875
8876         if (needed % 4) {
8877                 needed += 4-(needed % 4);
8878         }
8879 #endif
8880         *r->out.count   = count;
8881         *r->out.info    = info;
8882
8883  done:
8884         if (!W_ERROR_IS_OK(result)) {
8885                 return result;
8886         }
8887
8888         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8889                                                spoolss_EnumPrinterDataEx, 
8890                                                *r->out.info,
8891                                                *r->out.count);
8892         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8893         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8894
8895         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8896 }
8897
8898 /****************************************************************************
8899 ****************************************************************************/
8900
8901 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8902                                                  const char *servername,
8903                                                  const char *environment,
8904                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
8905 {
8906         WERROR werr;
8907         char *path = NULL;
8908
8909         werr = compose_spoolss_server_path(mem_ctx,
8910                                            servername,
8911                                            environment,
8912                                            SPOOLSS_PRTPROCS_PATH,
8913                                            &path);
8914         if (!W_ERROR_IS_OK(werr)) {
8915                 return werr;
8916         }
8917
8918         DEBUG(4,("print processor directory: [%s]\n", path));
8919
8920         r->directory_name = path;
8921
8922         return WERR_OK;
8923 }
8924
8925 /****************************************************************
8926  _spoolss_GetPrintProcessorDirectory
8927 ****************************************************************/
8928
8929 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8930                                            struct spoolss_GetPrintProcessorDirectory *r)
8931 {
8932         WERROR result;
8933
8934         /* that's an [in out] buffer */
8935
8936         if (!r->in.buffer && (r->in.offered != 0)) {
8937                 return WERR_INVALID_PARAM;
8938         }
8939
8940         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8941                 r->in.level));
8942
8943         *r->out.needed = 0;
8944
8945         /* r->in.level is ignored */
8946
8947         /* We always should reply with a local print processor directory so that
8948          * users are not forced to have a [prnproc$] share on the Samba spoolss
8949          * server - Guenther */
8950
8951         result = getprintprocessordirectory_level_1(p->mem_ctx,
8952                                                     NULL, /* r->in.server */
8953                                                     r->in.environment,
8954                                                     &r->out.info->info1);
8955         if (!W_ERROR_IS_OK(result)) {
8956                 TALLOC_FREE(r->out.info);
8957                 return result;
8958         }
8959
8960         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8961                                                                                    r->out.info, r->in.level);
8962         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8963
8964         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8965 }
8966
8967 /*******************************************************************
8968  ********************************************************************/
8969
8970 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8971                                const char *dllname)
8972 {
8973         enum ndr_err_code ndr_err;
8974         struct spoolss_MonitorUi ui;
8975
8976         ui.dll_name = dllname;
8977
8978         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8979                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8980         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8981                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8982         }
8983         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8984 }
8985
8986 /*******************************************************************
8987  Streams the monitor UI DLL name in UNICODE
8988 *******************************************************************/
8989
8990 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8991                                NT_USER_TOKEN *token, DATA_BLOB *in,
8992                                DATA_BLOB *out, uint32_t *needed)
8993 {
8994         const char *dllname = "tcpmonui.dll";
8995
8996         *needed = (strlen(dllname)+1) * 2;
8997
8998         if (out->length < *needed) {
8999                 return WERR_INSUFFICIENT_BUFFER;
9000         }
9001
9002         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9003                 return WERR_NOMEM;
9004         }
9005
9006         return WERR_OK;
9007 }
9008
9009 /*******************************************************************
9010  ********************************************************************/
9011
9012 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9013                              struct spoolss_PortData1 *port1,
9014                              const DATA_BLOB *buf)
9015 {
9016         enum ndr_err_code ndr_err;
9017         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9018                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9019         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9020                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9021         }
9022         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9023 }
9024
9025 /*******************************************************************
9026  ********************************************************************/
9027
9028 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9029                              struct spoolss_PortData2 *port2,
9030                              const DATA_BLOB *buf)
9031 {
9032         enum ndr_err_code ndr_err;
9033         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9034                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9035         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9036                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9037         }
9038         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9039 }
9040
9041 /*******************************************************************
9042  Create a new TCP/IP port
9043 *******************************************************************/
9044
9045 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9046                              NT_USER_TOKEN *token, DATA_BLOB *in,
9047                              DATA_BLOB *out, uint32_t *needed)
9048 {
9049         struct spoolss_PortData1 port1;
9050         struct spoolss_PortData2 port2;
9051         char *device_uri = NULL;
9052         uint32_t version;
9053
9054         const char *portname;
9055         const char *hostaddress;
9056         const char *queue;
9057         uint32_t port_number;
9058         uint32_t protocol;
9059
9060         /* peek for spoolss_PortData version */
9061
9062         if (!in || (in->length < (128 + 4))) {
9063                 return WERR_GENERAL_FAILURE;
9064         }
9065
9066         version = IVAL(in->data, 128);
9067
9068         switch (version) {
9069                 case 1:
9070                         ZERO_STRUCT(port1);
9071
9072                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9073                                 return WERR_NOMEM;
9074                         }
9075
9076                         portname        = port1.portname;
9077                         hostaddress     = port1.hostaddress;
9078                         queue           = port1.queue;
9079                         protocol        = port1.protocol;
9080                         port_number     = port1.port_number;
9081
9082                         break;
9083                 case 2:
9084                         ZERO_STRUCT(port2);
9085
9086                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9087                                 return WERR_NOMEM;
9088                         }
9089
9090                         portname        = port2.portname;
9091                         hostaddress     = port2.hostaddress;
9092                         queue           = port2.queue;
9093                         protocol        = port2.protocol;
9094                         port_number     = port2.port_number;
9095
9096                         break;
9097                 default:
9098                         DEBUG(1,("xcvtcp_addport: "
9099                                 "unknown version of port_data: %d\n", version));
9100                         return WERR_UNKNOWN_PORT;
9101         }
9102
9103         /* create the device URI and call the add_port_hook() */
9104
9105         switch (protocol) {
9106         case PROTOCOL_RAWTCP_TYPE:
9107                 device_uri = talloc_asprintf(mem_ctx,
9108                                 "socket://%s:%d/", hostaddress,
9109                                 port_number);
9110                 break;
9111
9112         case PROTOCOL_LPR_TYPE:
9113                 device_uri = talloc_asprintf(mem_ctx,
9114                         "lpr://%s/%s", hostaddress, queue );
9115                 break;
9116
9117         default:
9118                 return WERR_UNKNOWN_PORT;
9119         }
9120
9121         if (!device_uri) {
9122                 return WERR_NOMEM;
9123         }
9124
9125         return add_port_hook(mem_ctx, token, portname, device_uri);
9126 }
9127
9128 /*******************************************************************
9129 *******************************************************************/
9130
9131 struct xcv_api_table xcvtcp_cmds[] = {
9132         { "MonitorUI",  xcvtcp_monitorui },
9133         { "AddPort",    xcvtcp_addport},
9134         { NULL,         NULL }
9135 };
9136
9137 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9138                                      NT_USER_TOKEN *token, const char *command,
9139                                      DATA_BLOB *inbuf,
9140                                      DATA_BLOB *outbuf,
9141                                      uint32_t *needed )
9142 {
9143         int i;
9144
9145         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9146
9147         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9148                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9149                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9150         }
9151
9152         return WERR_BADFUNC;
9153 }
9154
9155 /*******************************************************************
9156 *******************************************************************/
9157 #if 0   /* don't support management using the "Local Port" monitor */
9158
9159 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9160                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9161                                  DATA_BLOB *out, uint32_t *needed)
9162 {
9163         const char *dllname = "localui.dll";
9164
9165         *needed = (strlen(dllname)+1) * 2;
9166
9167         if (out->length < *needed) {
9168                 return WERR_INSUFFICIENT_BUFFER;
9169         }
9170
9171         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9172                 return WERR_NOMEM;
9173         }
9174
9175         return WERR_OK;
9176 }
9177
9178 /*******************************************************************
9179 *******************************************************************/
9180
9181 struct xcv_api_table xcvlocal_cmds[] = {
9182         { "MonitorUI",  xcvlocal_monitorui },
9183         { NULL,         NULL }
9184 };
9185 #else
9186 struct xcv_api_table xcvlocal_cmds[] = {
9187         { NULL,         NULL }
9188 };
9189 #endif
9190
9191
9192
9193 /*******************************************************************
9194 *******************************************************************/
9195
9196 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9197                                        NT_USER_TOKEN *token, const char *command,
9198                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9199                                        uint32_t *needed)
9200 {
9201         int i;
9202
9203         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9204
9205         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9206                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9207                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9208         }
9209         return WERR_BADFUNC;
9210 }
9211
9212 /****************************************************************
9213  _spoolss_XcvData
9214 ****************************************************************/
9215
9216 WERROR _spoolss_XcvData(pipes_struct *p,
9217                         struct spoolss_XcvData *r)
9218 {
9219         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9220         DATA_BLOB out_data = data_blob_null;
9221         WERROR werror;
9222
9223         if (!Printer) {
9224                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9225                         OUR_HANDLE(r->in.handle)));
9226                 return WERR_BADFID;
9227         }
9228
9229         /* Has to be a handle to the TCP/IP port monitor */
9230
9231         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9232                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9233                 return WERR_BADFID;
9234         }
9235
9236         /* requires administrative access to the server */
9237
9238         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9239                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9240                 return WERR_ACCESS_DENIED;
9241         }
9242
9243         /* Allocate the outgoing buffer */
9244
9245         if (r->in.out_data_size) {
9246                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9247                 if (out_data.data == NULL) {
9248                         return WERR_NOMEM;
9249                 }
9250         }
9251
9252         switch ( Printer->printer_type ) {
9253         case SPLHND_PORTMON_TCP:
9254                 werror = process_xcvtcp_command(p->mem_ctx,
9255                                                 p->server_info->ptok,
9256                                                 r->in.function_name,
9257                                                 &r->in.in_data, &out_data,
9258                                                 r->out.needed);
9259                 break;
9260         case SPLHND_PORTMON_LOCAL:
9261                 werror = process_xcvlocal_command(p->mem_ctx,
9262                                                   p->server_info->ptok,
9263                                                   r->in.function_name,
9264                                                   &r->in.in_data, &out_data,
9265                                                   r->out.needed);
9266                 break;
9267         default:
9268                 werror = WERR_INVALID_PRINT_MONITOR;
9269         }
9270
9271         if (!W_ERROR_IS_OK(werror)) {
9272                 return werror;
9273         }
9274
9275         *r->out.status_code = 0;
9276
9277         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9278                 memcpy(r->out.out_data, out_data.data,
9279                         MIN(r->in.out_data_size, out_data.length));
9280         }
9281
9282         return WERR_OK;
9283 }
9284
9285 /****************************************************************
9286  _spoolss_AddPrintProcessor
9287 ****************************************************************/
9288
9289 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9290                                   struct spoolss_AddPrintProcessor *r)
9291 {
9292         /* for now, just indicate success and ignore the add.  We'll
9293            automatically set the winprint processor for printer
9294            entries later.  Used to debug the LexMark Optra S 1855 PCL
9295            driver --jerry */
9296
9297         return WERR_OK;
9298 }
9299
9300 /****************************************************************
9301  _spoolss_AddPort
9302 ****************************************************************/
9303
9304 WERROR _spoolss_AddPort(pipes_struct *p,
9305                         struct spoolss_AddPort *r)
9306 {
9307         /* do what w2k3 does */
9308
9309         return WERR_NOT_SUPPORTED;
9310 }
9311
9312 /****************************************************************
9313  _spoolss_GetPrinterDriver
9314 ****************************************************************/
9315
9316 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9317                                  struct spoolss_GetPrinterDriver *r)
9318 {
9319         p->rng_fault_state = true;
9320         return WERR_NOT_SUPPORTED;
9321 }
9322
9323 /****************************************************************
9324  _spoolss_ReadPrinter
9325 ****************************************************************/
9326
9327 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9328                             struct spoolss_ReadPrinter *r)
9329 {
9330         p->rng_fault_state = true;
9331         return WERR_NOT_SUPPORTED;
9332 }
9333
9334 /****************************************************************
9335  _spoolss_WaitForPrinterChange
9336 ****************************************************************/
9337
9338 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9339                                      struct spoolss_WaitForPrinterChange *r)
9340 {
9341         p->rng_fault_state = true;
9342         return WERR_NOT_SUPPORTED;
9343 }
9344
9345 /****************************************************************
9346  _spoolss_ConfigurePort
9347 ****************************************************************/
9348
9349 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9350                               struct spoolss_ConfigurePort *r)
9351 {
9352         p->rng_fault_state = true;
9353         return WERR_NOT_SUPPORTED;
9354 }
9355
9356 /****************************************************************
9357  _spoolss_DeletePort
9358 ****************************************************************/
9359
9360 WERROR _spoolss_DeletePort(pipes_struct *p,
9361                            struct spoolss_DeletePort *r)
9362 {
9363         p->rng_fault_state = true;
9364         return WERR_NOT_SUPPORTED;
9365 }
9366
9367 /****************************************************************
9368  _spoolss_CreatePrinterIC
9369 ****************************************************************/
9370
9371 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9372                                 struct spoolss_CreatePrinterIC *r)
9373 {
9374         p->rng_fault_state = true;
9375         return WERR_NOT_SUPPORTED;
9376 }
9377
9378 /****************************************************************
9379  _spoolss_PlayGDIScriptOnPrinterIC
9380 ****************************************************************/
9381
9382 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9383                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9384 {
9385         p->rng_fault_state = true;
9386         return WERR_NOT_SUPPORTED;
9387 }
9388
9389 /****************************************************************
9390  _spoolss_DeletePrinterIC
9391 ****************************************************************/
9392
9393 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9394                                 struct spoolss_DeletePrinterIC *r)
9395 {
9396         p->rng_fault_state = true;
9397         return WERR_NOT_SUPPORTED;
9398 }
9399
9400 /****************************************************************
9401  _spoolss_AddPrinterConnection
9402 ****************************************************************/
9403
9404 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9405                                      struct spoolss_AddPrinterConnection *r)
9406 {
9407         p->rng_fault_state = true;
9408         return WERR_NOT_SUPPORTED;
9409 }
9410
9411 /****************************************************************
9412  _spoolss_DeletePrinterConnection
9413 ****************************************************************/
9414
9415 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9416                                         struct spoolss_DeletePrinterConnection *r)
9417 {
9418         p->rng_fault_state = true;
9419         return WERR_NOT_SUPPORTED;
9420 }
9421
9422 /****************************************************************
9423  _spoolss_PrinterMessageBox
9424 ****************************************************************/
9425
9426 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9427                                   struct spoolss_PrinterMessageBox *r)
9428 {
9429         p->rng_fault_state = true;
9430         return WERR_NOT_SUPPORTED;
9431 }
9432
9433 /****************************************************************
9434  _spoolss_AddMonitor
9435 ****************************************************************/
9436
9437 WERROR _spoolss_AddMonitor(pipes_struct *p,
9438                            struct spoolss_AddMonitor *r)
9439 {
9440         p->rng_fault_state = true;
9441         return WERR_NOT_SUPPORTED;
9442 }
9443
9444 /****************************************************************
9445  _spoolss_DeleteMonitor
9446 ****************************************************************/
9447
9448 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9449                               struct spoolss_DeleteMonitor *r)
9450 {
9451         p->rng_fault_state = true;
9452         return WERR_NOT_SUPPORTED;
9453 }
9454
9455 /****************************************************************
9456  _spoolss_DeletePrintProcessor
9457 ****************************************************************/
9458
9459 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9460                                      struct spoolss_DeletePrintProcessor *r)
9461 {
9462         p->rng_fault_state = true;
9463         return WERR_NOT_SUPPORTED;
9464 }
9465
9466 /****************************************************************
9467  _spoolss_AddPrintProvidor
9468 ****************************************************************/
9469
9470 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9471                                  struct spoolss_AddPrintProvidor *r)
9472 {
9473         p->rng_fault_state = true;
9474         return WERR_NOT_SUPPORTED;
9475 }
9476
9477 /****************************************************************
9478  _spoolss_DeletePrintProvidor
9479 ****************************************************************/
9480
9481 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9482                                     struct spoolss_DeletePrintProvidor *r)
9483 {
9484         p->rng_fault_state = true;
9485         return WERR_NOT_SUPPORTED;
9486 }
9487
9488 /****************************************************************
9489  _spoolss_FindFirstPrinterChangeNotification
9490 ****************************************************************/
9491
9492 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9493                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9494 {
9495         p->rng_fault_state = true;
9496         return WERR_NOT_SUPPORTED;
9497 }
9498
9499 /****************************************************************
9500  _spoolss_FindNextPrinterChangeNotification
9501 ****************************************************************/
9502
9503 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9504                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9505 {
9506         p->rng_fault_state = true;
9507         return WERR_NOT_SUPPORTED;
9508 }
9509
9510 /****************************************************************
9511  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9512 ****************************************************************/
9513
9514 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9515                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9516 {
9517         p->rng_fault_state = true;
9518         return WERR_NOT_SUPPORTED;
9519 }
9520
9521 /****************************************************************
9522  _spoolss_ReplyOpenPrinter
9523 ****************************************************************/
9524
9525 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9526                                  struct spoolss_ReplyOpenPrinter *r)
9527 {
9528         p->rng_fault_state = true;
9529         return WERR_NOT_SUPPORTED;
9530 }
9531
9532 /****************************************************************
9533  _spoolss_RouterReplyPrinter
9534 ****************************************************************/
9535
9536 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9537                                    struct spoolss_RouterReplyPrinter *r)
9538 {
9539         p->rng_fault_state = true;
9540         return WERR_NOT_SUPPORTED;
9541 }
9542
9543 /****************************************************************
9544  _spoolss_ReplyClosePrinter
9545 ****************************************************************/
9546
9547 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9548                                   struct spoolss_ReplyClosePrinter *r)
9549 {
9550         p->rng_fault_state = true;
9551         return WERR_NOT_SUPPORTED;
9552 }
9553
9554 /****************************************************************
9555  _spoolss_AddPortEx
9556 ****************************************************************/
9557
9558 WERROR _spoolss_AddPortEx(pipes_struct *p,
9559                           struct spoolss_AddPortEx *r)
9560 {
9561         p->rng_fault_state = true;
9562         return WERR_NOT_SUPPORTED;
9563 }
9564
9565 /****************************************************************
9566  _spoolss_RouterFindFirstPrinterChangeNotification
9567 ****************************************************************/
9568
9569 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9570                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9571 {
9572         p->rng_fault_state = true;
9573         return WERR_NOT_SUPPORTED;
9574 }
9575
9576 /****************************************************************
9577  _spoolss_SpoolerInit
9578 ****************************************************************/
9579
9580 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9581                             struct spoolss_SpoolerInit *r)
9582 {
9583         p->rng_fault_state = true;
9584         return WERR_NOT_SUPPORTED;
9585 }
9586
9587 /****************************************************************
9588  _spoolss_ResetPrinterEx
9589 ****************************************************************/
9590
9591 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9592                                struct spoolss_ResetPrinterEx *r)
9593 {
9594         p->rng_fault_state = true;
9595         return WERR_NOT_SUPPORTED;
9596 }
9597
9598 /****************************************************************
9599  _spoolss_RouterReplyPrinterEx
9600 ****************************************************************/
9601
9602 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9603                                      struct spoolss_RouterReplyPrinterEx *r)
9604 {
9605         p->rng_fault_state = true;
9606         return WERR_NOT_SUPPORTED;
9607 }
9608
9609 /****************************************************************
9610  _spoolss_44
9611 ****************************************************************/
9612
9613 WERROR _spoolss_44(pipes_struct *p,
9614                    struct spoolss_44 *r)
9615 {
9616         p->rng_fault_state = true;
9617         return WERR_NOT_SUPPORTED;
9618 }
9619
9620 /****************************************************************
9621  _spoolss_47
9622 ****************************************************************/
9623
9624 WERROR _spoolss_47(pipes_struct *p,
9625                    struct spoolss_47 *r)
9626 {
9627         p->rng_fault_state = true;
9628         return WERR_NOT_SUPPORTED;
9629 }
9630
9631 /****************************************************************
9632  _spoolss_4a
9633 ****************************************************************/
9634
9635 WERROR _spoolss_4a(pipes_struct *p,
9636                    struct spoolss_4a *r)
9637 {
9638         p->rng_fault_state = true;
9639         return WERR_NOT_SUPPORTED;
9640 }
9641
9642 /****************************************************************
9643  _spoolss_4b
9644 ****************************************************************/
9645
9646 WERROR _spoolss_4b(pipes_struct *p,
9647                    struct spoolss_4b *r)
9648 {
9649         p->rng_fault_state = true;
9650         return WERR_NOT_SUPPORTED;
9651 }
9652
9653 /****************************************************************
9654  _spoolss_4c
9655 ****************************************************************/
9656
9657 WERROR _spoolss_4c(pipes_struct *p,
9658                    struct spoolss_4c *r)
9659 {
9660         p->rng_fault_state = true;
9661         return WERR_NOT_SUPPORTED;
9662 }
9663
9664 /****************************************************************
9665  _spoolss_53
9666 ****************************************************************/
9667
9668 WERROR _spoolss_53(pipes_struct *p,
9669                    struct spoolss_53 *r)
9670 {
9671         p->rng_fault_state = true;
9672         return WERR_NOT_SUPPORTED;
9673 }
9674
9675 /****************************************************************
9676  _spoolss_55
9677 ****************************************************************/
9678
9679 WERROR _spoolss_55(pipes_struct *p,
9680                    struct spoolss_55 *r)
9681 {
9682         p->rng_fault_state = true;
9683         return WERR_NOT_SUPPORTED;
9684 }
9685
9686 /****************************************************************
9687  _spoolss_56
9688 ****************************************************************/
9689
9690 WERROR _spoolss_56(pipes_struct *p,
9691                    struct spoolss_56 *r)
9692 {
9693         p->rng_fault_state = true;
9694         return WERR_NOT_SUPPORTED;
9695 }
9696
9697 /****************************************************************
9698  _spoolss_57
9699 ****************************************************************/
9700
9701 WERROR _spoolss_57(pipes_struct *p,
9702                    struct spoolss_57 *r)
9703 {
9704         p->rng_fault_state = true;
9705         return WERR_NOT_SUPPORTED;
9706 }
9707
9708 /****************************************************************
9709  _spoolss_5a
9710 ****************************************************************/
9711
9712 WERROR _spoolss_5a(pipes_struct *p,
9713                    struct spoolss_5a *r)
9714 {
9715         p->rng_fault_state = true;
9716         return WERR_NOT_SUPPORTED;
9717 }
9718
9719 /****************************************************************
9720  _spoolss_5b
9721 ****************************************************************/
9722
9723 WERROR _spoolss_5b(pipes_struct *p,
9724                    struct spoolss_5b *r)
9725 {
9726         p->rng_fault_state = true;
9727         return WERR_NOT_SUPPORTED;
9728 }
9729
9730 /****************************************************************
9731  _spoolss_5c
9732 ****************************************************************/
9733
9734 WERROR _spoolss_5c(pipes_struct *p,
9735                    struct spoolss_5c *r)
9736 {
9737         p->rng_fault_state = true;
9738         return WERR_NOT_SUPPORTED;
9739 }
9740
9741 /****************************************************************
9742  _spoolss_5d
9743 ****************************************************************/
9744
9745 WERROR _spoolss_5d(pipes_struct *p,
9746                    struct spoolss_5d *r)
9747 {
9748         p->rng_fault_state = true;
9749         return WERR_NOT_SUPPORTED;
9750 }
9751
9752 /****************************************************************
9753  _spoolss_5e
9754 ****************************************************************/
9755
9756 WERROR _spoolss_5e(pipes_struct *p,
9757                    struct spoolss_5e *r)
9758 {
9759         p->rng_fault_state = true;
9760         return WERR_NOT_SUPPORTED;
9761 }
9762
9763 /****************************************************************
9764  _spoolss_5f
9765 ****************************************************************/
9766
9767 WERROR _spoolss_5f(pipes_struct *p,
9768                    struct spoolss_5f *r)
9769 {
9770         p->rng_fault_state = true;
9771         return WERR_NOT_SUPPORTED;
9772 }
9773
9774 /****************************************************************
9775  _spoolss_60
9776 ****************************************************************/
9777
9778 WERROR _spoolss_60(pipes_struct *p,
9779                    struct spoolss_60 *r)
9780 {
9781         p->rng_fault_state = true;
9782         return WERR_NOT_SUPPORTED;
9783 }
9784
9785 /****************************************************************
9786  _spoolss_61
9787 ****************************************************************/
9788
9789 WERROR _spoolss_61(pipes_struct *p,
9790                    struct spoolss_61 *r)
9791 {
9792         p->rng_fault_state = true;
9793         return WERR_NOT_SUPPORTED;
9794 }
9795
9796 /****************************************************************
9797  _spoolss_62
9798 ****************************************************************/
9799
9800 WERROR _spoolss_62(pipes_struct *p,
9801                    struct spoolss_62 *r)
9802 {
9803         p->rng_fault_state = true;
9804         return WERR_NOT_SUPPORTED;
9805 }
9806
9807 /****************************************************************
9808  _spoolss_63
9809 ****************************************************************/
9810
9811 WERROR _spoolss_63(pipes_struct *p,
9812                    struct spoolss_63 *r)
9813 {
9814         p->rng_fault_state = true;
9815         return WERR_NOT_SUPPORTED;
9816 }
9817
9818 /****************************************************************
9819  _spoolss_64
9820 ****************************************************************/
9821
9822 WERROR _spoolss_64(pipes_struct *p,
9823                    struct spoolss_64 *r)
9824 {
9825         p->rng_fault_state = true;
9826         return WERR_NOT_SUPPORTED;
9827 }
9828
9829 /****************************************************************
9830  _spoolss_65
9831 ****************************************************************/
9832
9833 WERROR _spoolss_65(pipes_struct *p,
9834                    struct spoolss_65 *r)
9835 {
9836         p->rng_fault_state = true;
9837         return WERR_NOT_SUPPORTED;
9838 }
9839
9840 /****************************************************************
9841  _spoolss_GetCorePrinterDrivers
9842 ****************************************************************/
9843
9844 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9845                                       struct spoolss_GetCorePrinterDrivers *r)
9846 {
9847         p->rng_fault_state = true;
9848         return WERR_NOT_SUPPORTED;
9849 }
9850
9851 /****************************************************************
9852  _spoolss_67
9853 ****************************************************************/
9854
9855 WERROR _spoolss_67(pipes_struct *p,
9856                    struct spoolss_67 *r)
9857 {
9858         p->rng_fault_state = true;
9859         return WERR_NOT_SUPPORTED;
9860 }
9861
9862 /****************************************************************
9863  _spoolss_GetPrinterDriverPackagePath
9864 ****************************************************************/
9865
9866 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9867                                             struct spoolss_GetPrinterDriverPackagePath *r)
9868 {
9869         p->rng_fault_state = true;
9870         return WERR_NOT_SUPPORTED;
9871 }
9872
9873 /****************************************************************
9874  _spoolss_69
9875 ****************************************************************/
9876
9877 WERROR _spoolss_69(pipes_struct *p,
9878                    struct spoolss_69 *r)
9879 {
9880         p->rng_fault_state = true;
9881         return WERR_NOT_SUPPORTED;
9882 }
9883
9884 /****************************************************************
9885  _spoolss_6a
9886 ****************************************************************/
9887
9888 WERROR _spoolss_6a(pipes_struct *p,
9889                    struct spoolss_6a *r)
9890 {
9891         p->rng_fault_state = true;
9892         return WERR_NOT_SUPPORTED;
9893 }
9894
9895 /****************************************************************
9896  _spoolss_6b
9897 ****************************************************************/
9898
9899 WERROR _spoolss_6b(pipes_struct *p,
9900                    struct spoolss_6b *r)
9901 {
9902         p->rng_fault_state = true;
9903         return WERR_NOT_SUPPORTED;
9904 }
9905
9906 /****************************************************************
9907  _spoolss_6c
9908 ****************************************************************/
9909
9910 WERROR _spoolss_6c(pipes_struct *p,
9911                    struct spoolss_6c *r)
9912 {
9913         p->rng_fault_state = true;
9914         return WERR_NOT_SUPPORTED;
9915 }
9916
9917 /****************************************************************
9918  _spoolss_6d
9919 ****************************************************************/
9920
9921 WERROR _spoolss_6d(pipes_struct *p,
9922                    struct spoolss_6d *r)
9923 {
9924         p->rng_fault_state = true;
9925         return WERR_NOT_SUPPORTED;
9926 }