s3-spoolss: Migrated spoolss_SetPrinterDataEx to the winreg functions.
[abartlet/samba.git/.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "srv_spoolss_util.h"
31 #include "../librpc/gen_ndr/srv_spoolss.h"
32 #include "../librpc/gen_ndr/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "librpc/gen_ndr/messaging.h"
35 #include "registry.h"
36 #include "registry/reg_objects.h"
37
38 /* macros stolen from s4 spoolss server */
39 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
40         ((info)?ndr_size_##fn(info, level, 0):0)
41
42 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
43         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
44
45 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
46         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
47
48 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
49
50
51 extern userdom_struct current_user_info;
52
53 #undef DBGC_CLASS
54 #define DBGC_CLASS DBGC_RPC_SRV
55
56 #ifndef MAX_OPEN_PRINTER_EXS
57 #define MAX_OPEN_PRINTER_EXS 50
58 #endif
59
60 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
61
62 static Printer_entry *printers_list;
63
64 typedef struct _counter_printer_0 {
65         struct _counter_printer_0 *next;
66         struct _counter_printer_0 *prev;
67
68         int snum;
69         uint32_t counter;
70 } counter_printer_0;
71
72 static counter_printer_0 *counter_list;
73
74 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
75 static uint32_t smb_connections = 0;
76
77
78 /* in printing/nt_printing.c */
79
80 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
81
82 /* API table for Xcv Monitor functions */
83
84 struct xcv_api_table {
85         const char *name;
86         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
87 };
88
89 /********************************************************************
90  * Canonicalize servername.
91  ********************************************************************/
92
93 static const char *canon_servername(const char *servername)
94 {
95         const char *pservername = servername;
96         while (*pservername == '\\') {
97                 pservername++;
98         }
99         return pservername;
100 }
101
102 /* translate between internal status numbers and NT status numbers */
103 static int nt_printj_status(int v)
104 {
105         switch (v) {
106         case LPQ_QUEUED:
107                 return 0;
108         case LPQ_PAUSED:
109                 return JOB_STATUS_PAUSED;
110         case LPQ_SPOOLING:
111                 return JOB_STATUS_SPOOLING;
112         case LPQ_PRINTING:
113                 return JOB_STATUS_PRINTING;
114         case LPQ_ERROR:
115                 return JOB_STATUS_ERROR;
116         case LPQ_DELETING:
117                 return JOB_STATUS_DELETING;
118         case LPQ_OFFLINE:
119                 return JOB_STATUS_OFFLINE;
120         case LPQ_PAPEROUT:
121                 return JOB_STATUS_PAPEROUT;
122         case LPQ_PRINTED:
123                 return JOB_STATUS_PRINTED;
124         case LPQ_DELETED:
125                 return JOB_STATUS_DELETED;
126         case LPQ_BLOCKED:
127                 return JOB_STATUS_BLOCKED_DEVQ;
128         case LPQ_USER_INTERVENTION:
129                 return JOB_STATUS_USER_INTERVENTION;
130         }
131         return 0;
132 }
133
134 static int nt_printq_status(int v)
135 {
136         switch (v) {
137         case LPQ_PAUSED:
138                 return PRINTER_STATUS_PAUSED;
139         case LPQ_QUEUED:
140         case LPQ_SPOOLING:
141         case LPQ_PRINTING:
142                 return 0;
143         }
144         return 0;
145 }
146
147 /***************************************************************************
148  Disconnect from the client
149 ****************************************************************************/
150
151 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
152 {
153         WERROR result;
154         NTSTATUS status;
155
156         /*
157          * Tell the specific printing tdb we no longer want messages for this printer
158          * by deregistering our PID.
159          */
160
161         if (!print_notify_deregister_pid(snum))
162                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163
164         /* weird if the test succeds !!! */
165         if (smb_connections==0) {
166                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167                 return;
168         }
169
170         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
171                                                   handle,
172                                                   &result);
173         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
174                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
175                         win_errstr(result)));
176
177         /* if it's the last connection, deconnect the IPC$ share */
178         if (smb_connections==1) {
179
180                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
181                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182
183                 messaging_deregister(smbd_messaging_context(),
184                                      MSG_PRINTER_NOTIFY2, NULL);
185
186                 /* Tell the connections db we're no longer interested in
187                  * printer notify messages. */
188
189                 serverid_register_msg_flags(
190                         messaging_server_id(smbd_messaging_context()),
191                         false, FLAG_MSG_PRINT_NOTIFY);
192         }
193
194         smb_connections--;
195 }
196
197 /****************************************************************************
198  Functions to free a printer entry datastruct.
199 ****************************************************************************/
200
201 static int printer_entry_destructor(Printer_entry *Printer)
202 {
203         if (Printer->notify.client_connected == true) {
204                 int snum = -1;
205
206                 if ( Printer->printer_type == SPLHND_SERVER) {
207                         snum = -1;
208                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
209                 } else if (Printer->printer_type == SPLHND_PRINTER) {
210                         snum = print_queue_snum(Printer->sharename);
211                         if (snum != -1)
212                                 srv_spoolss_replycloseprinter(snum,
213                                                 &Printer->notify.client_hnd);
214                 }
215         }
216
217         Printer->notify.flags=0;
218         Printer->notify.options=0;
219         Printer->notify.localmachine[0]='\0';
220         Printer->notify.printerlocal=0;
221         TALLOC_FREE(Printer->notify.option);
222         Printer->notify.client_connected = false;
223
224         TALLOC_FREE(Printer->devmode);
225         free_a_printer( &Printer->printer_info, 2 );
226
227         /* Remove from the internal list. */
228         DLIST_REMOVE(printers_list, Printer);
229         return 0;
230 }
231
232 /****************************************************************************
233   find printer index by handle
234 ****************************************************************************/
235
236 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
237                                                 struct policy_handle *hnd)
238 {
239         Printer_entry *find_printer = NULL;
240
241         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
242                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
243                 return NULL;
244         }
245
246         return find_printer;
247 }
248
249 /****************************************************************************
250  Close printer index by handle.
251 ****************************************************************************/
252
253 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
254 {
255         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
256
257         if (!Printer) {
258                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
259                         OUR_HANDLE(hnd)));
260                 return false;
261         }
262
263         close_policy_hnd(p, hnd);
264
265         return true;
266 }
267
268 /****************************************************************************
269  Delete a printer given a handle.
270 ****************************************************************************/
271
272 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
273 {
274         char *cmd = lp_deleteprinter_cmd();
275         char *command = NULL;
276         int ret;
277         SE_PRIV se_printop = SE_PRINT_OPERATOR;
278         bool is_print_op = false;
279
280         /* can't fail if we don't try */
281
282         if ( !*cmd )
283                 return WERR_OK;
284
285         command = talloc_asprintf(ctx,
286                         "%s \"%s\"",
287                         cmd, sharename);
288         if (!command) {
289                 return WERR_NOMEM;
290         }
291         if ( token )
292                 is_print_op = user_has_privileges( token, &se_printop );
293
294         DEBUG(10,("Running [%s]\n", command));
295
296         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
297
298         if ( is_print_op )
299                 become_root();
300
301         if ( (ret = smbrun(command, NULL)) == 0 ) {
302                 /* Tell everyone we updated smb.conf. */
303                 message_send_all(smbd_messaging_context(),
304                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
305         }
306
307         if ( is_print_op )
308                 unbecome_root();
309
310         /********** END SePrintOperatorPrivlege BLOCK **********/
311
312         DEBUGADD(10,("returned [%d]\n", ret));
313
314         TALLOC_FREE(command);
315
316         if (ret != 0)
317                 return WERR_BADFID; /* What to return here? */
318
319         /* go ahead and re-read the services immediately */
320         become_root();
321         reload_services(false);
322         unbecome_root();
323
324         if ( lp_servicenumber( sharename )  > 0 )
325                 return WERR_ACCESS_DENIED;
326
327         return WERR_OK;
328 }
329
330 /****************************************************************************
331  Delete a printer given a handle.
332 ****************************************************************************/
333
334 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
335 {
336         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
337
338         if (!Printer) {
339                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
340                         OUR_HANDLE(hnd)));
341                 return WERR_BADFID;
342         }
343
344         /*
345          * It turns out that Windows allows delete printer on a handle
346          * opened by an admin user, then used on a pipe handle created
347          * by an anonymous user..... but they're working on security.... riiight !
348          * JRA.
349          */
350
351         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
352                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
353                 return WERR_ACCESS_DENIED;
354         }
355
356         /* this does not need a become root since the access check has been
357            done on the handle already */
358
359         if (del_a_printer( Printer->sharename ) != 0) {
360                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
361                 return WERR_BADFID;
362         }
363
364         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
365                                    Printer->sharename );
366 }
367
368 /****************************************************************************
369  Return the snum of a printer corresponding to an handle.
370 ****************************************************************************/
371
372 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
373                              int *number, struct share_params **params)
374 {
375         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
376
377         if (!Printer) {
378                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
379                         OUR_HANDLE(hnd)));
380                 return false;
381         }
382
383         switch (Printer->printer_type) {
384                 case SPLHND_PRINTER:
385                         DEBUG(4,("short name:%s\n", Printer->sharename));
386                         *number = print_queue_snum(Printer->sharename);
387                         return (*number != -1);
388                 case SPLHND_SERVER:
389                         return false;
390                 default:
391                         return false;
392         }
393 }
394
395 /****************************************************************************
396  Set printer handle type.
397  Check if it's \\server or \\server\printer
398 ****************************************************************************/
399
400 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
401 {
402         DEBUG(3,("Setting printer type=%s\n", handlename));
403
404         if ( strlen(handlename) < 3 ) {
405                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
406                 return false;
407         }
408
409         /* it's a print server */
410         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
411                 DEBUGADD(4,("Printer is a print server\n"));
412                 Printer->printer_type = SPLHND_SERVER;
413         }
414         /* it's a printer (set_printer_hnd_name() will handle port monitors */
415         else {
416                 DEBUGADD(4,("Printer is a printer\n"));
417                 Printer->printer_type = SPLHND_PRINTER;
418         }
419
420         return true;
421 }
422
423 /****************************************************************************
424  Set printer handle name..  Accept names like \\server, \\server\printer,
425  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
426  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
427  XcvDataPort() interface.
428 ****************************************************************************/
429
430 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
431 {
432         int snum;
433         int n_services=lp_numservices();
434         char *aprinter, *printername;
435         const char *servername;
436         fstring sname;
437         bool found = false;
438         NT_PRINTER_INFO_LEVEL *printer = NULL;
439         WERROR result;
440
441         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
442                 (unsigned long)strlen(handlename)));
443
444         aprinter = CONST_DISCARD(char *, handlename);
445         if ( *handlename == '\\' ) {
446                 servername = canon_servername(handlename);
447                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
448                         *aprinter = '\0';
449                         aprinter++;
450                 }
451         } else {
452                 servername = global_myname();
453         }
454
455         /* save the servername to fill in replies on this handle */
456
457         if ( !is_myname_or_ipaddr( servername ) )
458                 return false;
459
460         fstrcpy( Printer->servername, servername );
461
462         if ( Printer->printer_type == SPLHND_SERVER )
463                 return true;
464
465         if ( Printer->printer_type != SPLHND_PRINTER )
466                 return false;
467
468         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
469
470         /* check for the Port Monitor Interface */
471
472         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
473                 Printer->printer_type = SPLHND_PORTMON_TCP;
474                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
475                 found = true;
476         }
477         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
478                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
479                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
480                 found = true;
481         }
482
483         /* Search all sharenames first as this is easier than pulling
484            the printer_info_2 off of disk. Don't use find_service() since
485            that calls out to map_username() */
486
487         /* do another loop to look for printernames */
488
489         for (snum=0; !found && snum<n_services; snum++) {
490
491                 /* no point going on if this is not a printer */
492
493                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
494                         continue;
495
496                 fstrcpy(sname, lp_servicename(snum));
497                 if ( strequal( aprinter, sname ) ) {
498                         found = true;
499                         break;
500                 }
501
502                 /* no point looking up the printer object if
503                    we aren't allowing printername != sharename */
504
505                 if ( lp_force_printername(snum) )
506                         continue;
507
508                 fstrcpy(sname, lp_servicename(snum));
509
510                 printer = NULL;
511
512                 /* This call doesn't fill in the location or comment from
513                  * a CUPS server for efficiency with large numbers of printers.
514                  * JRA.
515                  */
516
517                 result = get_a_printer_search( NULL, &printer, 2, sname );
518                 if ( !W_ERROR_IS_OK(result) ) {
519                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
520                                 sname, win_errstr(result)));
521                         continue;
522                 }
523
524                 /* printername is always returned as \\server\printername */
525                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
526                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
527                                 printer->info_2->printername));
528                         free_a_printer( &printer, 2);
529                         continue;
530                 }
531
532                 printername++;
533
534                 if ( strequal(printername, aprinter) ) {
535                         free_a_printer( &printer, 2);
536                         found = true;
537                         break;
538                 }
539
540                 DEBUGADD(10, ("printername: %s\n", printername));
541
542                 free_a_printer( &printer, 2);
543         }
544
545         free_a_printer( &printer, 2);
546
547         if ( !found ) {
548                 DEBUGADD(4,("Printer not found\n"));
549                 return false;
550         }
551
552         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
553
554         fstrcpy(Printer->sharename, sname);
555
556         return true;
557 }
558
559 /****************************************************************************
560  Find first available printer slot. creates a printer handle for you.
561  ****************************************************************************/
562
563 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
564                              const char *name, uint32_t access_granted)
565 {
566         Printer_entry *new_printer;
567
568         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
569
570         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
571         if (new_printer == NULL) {
572                 return false;
573         }
574         talloc_set_destructor(new_printer, printer_entry_destructor);
575
576         if (!create_policy_hnd(p, hnd, new_printer)) {
577                 TALLOC_FREE(new_printer);
578                 return false;
579         }
580
581         /* Add to the internal list. */
582         DLIST_ADD(printers_list, new_printer);
583
584         new_printer->notify.option=NULL;
585
586         if (!set_printer_hnd_printertype(new_printer, name)) {
587                 close_printer_handle(p, hnd);
588                 return false;
589         }
590
591         if (!set_printer_hnd_name(new_printer, name)) {
592                 close_printer_handle(p, hnd);
593                 return false;
594         }
595
596         new_printer->access_granted = access_granted;
597
598         DEBUG(5, ("%d printer handles active\n",
599                   (int)num_pipe_handles(p)));
600
601         return true;
602 }
603
604 /***************************************************************************
605  check to see if the client motify handle is monitoring the notification
606  given by (notify_type, notify_field).
607  **************************************************************************/
608
609 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
610                                       uint16_t notify_field)
611 {
612         return true;
613 }
614
615 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
616                                 uint16_t notify_field)
617 {
618         struct spoolss_NotifyOption *option = p->notify.option;
619         uint32_t i, j;
620
621         /*
622          * Flags should always be zero when the change notify
623          * is registered by the client's spooler.  A user Win32 app
624          * might use the flags though instead of the NOTIFY_OPTION_INFO
625          * --jerry
626          */
627
628         if (!option) {
629                 return false;
630         }
631
632         if (p->notify.flags)
633                 return is_monitoring_event_flags(
634                         p->notify.flags, notify_type, notify_field);
635
636         for (i = 0; i < option->count; i++) {
637
638                 /* Check match for notify_type */
639
640                 if (option->types[i].type != notify_type)
641                         continue;
642
643                 /* Check match for field */
644
645                 for (j = 0; j < option->types[i].count; j++) {
646                         if (option->types[i].fields[j].field == notify_field) {
647                                 return true;
648                         }
649                 }
650         }
651
652         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
653                    p->servername, p->sharename, notify_type, notify_field));
654
655         return false;
656 }
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
659         _data->data.integer[0] = _integer; \
660         _data->data.integer[1] = 0;
661
662
663 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
664         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
665         if (!_data->data.string.string) {\
666                 _data->data.string.size = 0; \
667         } \
668         _data->data.string.size = strlen_m_term(_p) * 2;
669
670 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
671         _data->data.devmode.devmode = _devmode;
672
673 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
674         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
675         if (!_data->data.sd.sd) { \
676                 _data->data.sd.sd_size = 0; \
677         } \
678         _data->data.sd.sd_size = _size;
679
680 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
681                                    struct tm *t,
682                                    const char **pp,
683                                    uint32_t *plen)
684 {
685         struct spoolss_Time st;
686         uint32_t len = 16;
687         char *p;
688
689         if (!init_systemtime(&st, t)) {
690                 return;
691         }
692
693         p = talloc_array(mem_ctx, char, len);
694         if (!p) {
695                 return;
696         }
697
698         /*
699          * Systemtime must be linearized as a set of UINT16's.
700          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
701          */
702
703         SSVAL(p, 0, st.year);
704         SSVAL(p, 2, st.month);
705         SSVAL(p, 4, st.day_of_week);
706         SSVAL(p, 6, st.day);
707         SSVAL(p, 8, st.hour);
708         SSVAL(p, 10, st.minute);
709         SSVAL(p, 12, st.second);
710         SSVAL(p, 14, st.millisecond);
711
712         *pp = p;
713         *plen = len;
714 }
715
716 /* Convert a notification message to a struct spoolss_Notify */
717
718 static void notify_one_value(struct spoolss_notify_msg *msg,
719                              struct spoolss_Notify *data,
720                              TALLOC_CTX *mem_ctx)
721 {
722         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
723 }
724
725 static void notify_string(struct spoolss_notify_msg *msg,
726                           struct spoolss_Notify *data,
727                           TALLOC_CTX *mem_ctx)
728 {
729         /* The length of the message includes the trailing \0 */
730
731         data->data.string.size = msg->len * 2;
732         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
733         if (!data->data.string.string) {
734                 data->data.string.size = 0;
735                 return;
736         }
737 }
738
739 static void notify_system_time(struct spoolss_notify_msg *msg,
740                                struct spoolss_Notify *data,
741                                TALLOC_CTX *mem_ctx)
742 {
743         data->data.string.string = NULL;
744         data->data.string.size = 0;
745
746         if (msg->len != sizeof(time_t)) {
747                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
748                           msg->len));
749                 return;
750         }
751
752         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
753                                &data->data.string.string,
754                                &data->data.string.size);
755 }
756
757 struct notify2_message_table {
758         const char *name;
759         void (*fn)(struct spoolss_notify_msg *msg,
760                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
761 };
762
763 static struct notify2_message_table printer_notify_table[] = {
764         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
765         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
766         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
767         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
768         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
769         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
770         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
771         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
772         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
773         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
774         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
775         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
776         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
777         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
778         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
779         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
780         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
781         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
782         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
783 };
784
785 static struct notify2_message_table job_notify_table[] = {
786         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
787         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
788         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
789         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
790         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
791         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
792         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
793         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
794         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
795         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
796         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
797         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
798         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
799         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
800         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
801         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
802         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
803         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
804         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
805         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
806         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
807         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
808         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
809         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
810 };
811
812
813 /***********************************************************************
814  Allocate talloc context for container object
815  **********************************************************************/
816
817 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
818 {
819         if ( !ctr )
820                 return;
821
822         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
823
824         return;
825 }
826
827 /***********************************************************************
828  release all allocated memory and zero out structure
829  **********************************************************************/
830
831 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
832 {
833         if ( !ctr )
834                 return;
835
836         if ( ctr->ctx )
837                 talloc_destroy(ctr->ctx);
838
839         ZERO_STRUCTP(ctr);
840
841         return;
842 }
843
844 /***********************************************************************
845  **********************************************************************/
846
847 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 {
849         if ( !ctr )
850                 return NULL;
851
852         return ctr->ctx;
853 }
854
855 /***********************************************************************
856  **********************************************************************/
857
858 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
859 {
860         if ( !ctr || !ctr->msg_groups )
861                 return NULL;
862
863         if ( idx >= ctr->num_groups )
864                 return NULL;
865
866         return &ctr->msg_groups[idx];
867
868 }
869
870 /***********************************************************************
871  How many groups of change messages do we have ?
872  **********************************************************************/
873
874 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
875 {
876         if ( !ctr )
877                 return 0;
878
879         return ctr->num_groups;
880 }
881
882 /***********************************************************************
883  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
884  **********************************************************************/
885
886 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
887 {
888         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
889         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
890         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
891         int                             i, new_slot;
892
893         if ( !ctr || !msg )
894                 return 0;
895
896         /* loop over all groups looking for a matching printer name */
897
898         for ( i=0; i<ctr->num_groups; i++ ) {
899                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
900                         break;
901         }
902
903         /* add a new group? */
904
905         if ( i == ctr->num_groups ) {
906                 ctr->num_groups++;
907
908                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
909                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
910                         return 0;
911                 }
912                 ctr->msg_groups = groups;
913
914                 /* clear the new entry and set the printer name */
915
916                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
917                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
918         }
919
920         /* add the change messages; 'i' is the correct index now regardless */
921
922         msg_grp = &ctr->msg_groups[i];
923
924         msg_grp->num_msgs++;
925
926         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
927                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
928                 return 0;
929         }
930         msg_grp->msgs = msg_list;
931
932         new_slot = msg_grp->num_msgs-1;
933         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
934
935         /* need to allocate own copy of data */
936
937         if ( msg->len != 0 )
938                 msg_grp->msgs[new_slot].notify.data = (char *)
939                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
940
941         return ctr->num_groups;
942 }
943
944 void construct_info_data(struct spoolss_Notify *info_data,
945                          enum spoolss_NotifyType type,
946                          uint16_t field,
947                          int id);
948
949 /***********************************************************************
950  Send a change notication message on all handles which have a call
951  back registered
952  **********************************************************************/
953
954 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
955 {
956         Printer_entry            *p;
957         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
958         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
959         SPOOLSS_NOTIFY_MSG       *messages;
960         int                      sending_msg_count;
961
962         if ( !msg_group ) {
963                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
964                 return;
965         }
966
967         messages = msg_group->msgs;
968
969         if ( !messages ) {
970                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
971                 return;
972         }
973
974         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
975
976         /* loop over all printers */
977
978         for (p = printers_list; p; p = p->next) {
979                 struct spoolss_Notify *notifies;
980                 uint32_t count = 0;
981                 uint32_t id;
982                 int     i;
983
984                 /* Is there notification on this handle? */
985
986                 if ( !p->notify.client_connected )
987                         continue;
988
989                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
990
991                 /* For this printer?  Print servers always receive
992                    notifications. */
993
994                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
995                     ( !strequal(msg_group->printername, p->sharename) ) )
996                         continue;
997
998                 DEBUG(10,("Our printer\n"));
999
1000                 /* allocate the max entries possible */
1001
1002                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1003                 if (!notifies) {
1004                         return;
1005                 }
1006
1007                 /* build the array of change notifications */
1008
1009                 sending_msg_count = 0;
1010
1011                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1012                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1013
1014                         /* Are we monitoring this event? */
1015
1016                         if (!is_monitoring_event(p, msg->type, msg->field))
1017                                 continue;
1018
1019                         sending_msg_count++;
1020
1021
1022                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1023                                 msg->type, msg->field, p->sharename));
1024
1025                         /*
1026                          * if the is a printer notification handle and not a job notification
1027                          * type, then set the id to 0.  Other wise just use what was specified
1028                          * in the message.
1029                          *
1030                          * When registering change notification on a print server handle
1031                          * we always need to send back the id (snum) matching the printer
1032                          * for which the change took place.  For change notify registered
1033                          * on a printer handle, this does not matter and the id should be 0.
1034                          *
1035                          * --jerry
1036                          */
1037
1038                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1039                                 id = 0;
1040                         else
1041                                 id = msg->id;
1042
1043
1044                         /* Convert unix jobid to smb jobid */
1045
1046                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1047                                 id = sysjob_to_jobid(msg->id);
1048
1049                                 if (id == -1) {
1050                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1051                                         goto done;
1052                                 }
1053                         }
1054
1055                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1056
1057                         switch(msg->type) {
1058                         case PRINTER_NOTIFY_TYPE:
1059                                 if ( printer_notify_table[msg->field].fn )
1060                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1061                                 break;
1062
1063                         case JOB_NOTIFY_TYPE:
1064                                 if ( job_notify_table[msg->field].fn )
1065                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1066                                 break;
1067
1068                         default:
1069                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1070                                 goto done;
1071                         }
1072
1073                         count++;
1074                 }
1075
1076                 if ( sending_msg_count ) {
1077                         NTSTATUS status;
1078                         WERROR werr;
1079                         union spoolss_ReplyPrinterInfo info;
1080                         struct spoolss_NotifyInfo info0;
1081                         uint32_t reply_result;
1082
1083                         info0.version   = 0x2;
1084                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1085                         info0.count     = count;
1086                         info0.notifies  = notifies;
1087
1088                         info.info0 = &info0;
1089
1090                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1091                                                                      &p->notify.client_hnd,
1092                                                                      p->notify.change, /* color */
1093                                                                      p->notify.flags,
1094                                                                      &reply_result,
1095                                                                      0, /* reply_type, must be 0 */
1096                                                                      info,
1097                                                                      &werr);
1098                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1099                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1100                                         notify_cli_pipe->srv_name_slash,
1101                                         win_errstr(werr)));
1102                         }
1103                         switch (reply_result) {
1104                                 case 0:
1105                                         break;
1106                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1107                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1108                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1109                                         break;
1110                                 default:
1111                                         break;
1112                         }
1113                 }
1114         }
1115
1116 done:
1117         DEBUG(8,("send_notify2_changes: Exit...\n"));
1118         return;
1119 }
1120
1121 /***********************************************************************
1122  **********************************************************************/
1123
1124 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1125 {
1126
1127         uint32_t tv_sec, tv_usec;
1128         size_t offset = 0;
1129
1130         /* Unpack message */
1131
1132         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1133                              msg->printer);
1134
1135         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1136                                 &tv_sec, &tv_usec,
1137                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1138
1139         if (msg->len == 0)
1140                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1141                            &msg->notify.value[0], &msg->notify.value[1]);
1142         else
1143                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1144                            &msg->len, &msg->notify.data);
1145
1146         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1147                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1148
1149         tv->tv_sec = tv_sec;
1150         tv->tv_usec = tv_usec;
1151
1152         if (msg->len == 0)
1153                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1154                           msg->notify.value[1]));
1155         else
1156                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1157
1158         return true;
1159 }
1160
1161 /********************************************************************
1162  Receive a notify2 message list
1163  ********************************************************************/
1164
1165 static void receive_notify2_message_list(struct messaging_context *msg,
1166                                          void *private_data,
1167                                          uint32_t msg_type,
1168                                          struct server_id server_id,
1169                                          DATA_BLOB *data)
1170 {
1171         size_t                  msg_count, i;
1172         char                    *buf = (char *)data->data;
1173         char                    *msg_ptr;
1174         size_t                  msg_len;
1175         SPOOLSS_NOTIFY_MSG      notify;
1176         SPOOLSS_NOTIFY_MSG_CTR  messages;
1177         int                     num_groups;
1178
1179         if (data->length < 4) {
1180                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1181                 return;
1182         }
1183
1184         msg_count = IVAL(buf, 0);
1185         msg_ptr = buf + 4;
1186
1187         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1188
1189         if (msg_count == 0) {
1190                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1191                 return;
1192         }
1193
1194         /* initialize the container */
1195
1196         ZERO_STRUCT( messages );
1197         notify_msg_ctr_init( &messages );
1198
1199         /*
1200          * build message groups for each printer identified
1201          * in a change_notify msg.  Remember that a PCN message
1202          * includes the handle returned for the srv_spoolss_replyopenprinter()
1203          * call.  Therefore messages are grouped according to printer handle.
1204          */
1205
1206         for ( i=0; i<msg_count; i++ ) {
1207                 struct timeval msg_tv;
1208
1209                 if (msg_ptr + 4 - buf > data->length) {
1210                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1211                         return;
1212                 }
1213
1214                 msg_len = IVAL(msg_ptr,0);
1215                 msg_ptr += 4;
1216
1217                 if (msg_ptr + msg_len - buf > data->length) {
1218                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1219                         return;
1220                 }
1221
1222                 /* unpack messages */
1223
1224                 ZERO_STRUCT( notify );
1225                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1226                 msg_ptr += msg_len;
1227
1228                 /* add to correct list in container */
1229
1230                 notify_msg_ctr_addmsg( &messages, &notify );
1231
1232                 /* free memory that might have been allocated by notify2_unpack_msg() */
1233
1234                 if ( notify.len != 0 )
1235                         SAFE_FREE( notify.notify.data );
1236         }
1237
1238         /* process each group of messages */
1239
1240         num_groups = notify_msg_ctr_numgroups( &messages );
1241         for ( i=0; i<num_groups; i++ )
1242                 send_notify2_changes( &messages, i );
1243
1244
1245         /* cleanup */
1246
1247         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1248                 (uint32_t)msg_count ));
1249
1250         notify_msg_ctr_destroy( &messages );
1251
1252         return;
1253 }
1254
1255 /********************************************************************
1256  Send a message to ourself about new driver being installed
1257  so we can upgrade the information for each printer bound to this
1258  driver
1259  ********************************************************************/
1260
1261 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1262 {
1263         int len = strlen(drivername);
1264
1265         if (!len)
1266                 return false;
1267
1268         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1269                 drivername));
1270
1271         messaging_send_buf(smbd_messaging_context(),
1272                            messaging_server_id(smbd_messaging_context()),
1273                            MSG_PRINTER_DRVUPGRADE,
1274                            (uint8_t *)drivername, len+1);
1275
1276         return true;
1277 }
1278
1279 /**********************************************************************
1280  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1281  over all printers, upgrading ones as necessary
1282  **********************************************************************/
1283
1284 void do_drv_upgrade_printer(struct messaging_context *msg,
1285                             void *private_data,
1286                             uint32_t msg_type,
1287                             struct server_id server_id,
1288                             DATA_BLOB *data)
1289 {
1290         fstring drivername;
1291         int snum;
1292         int n_services = lp_numservices();
1293         size_t len;
1294
1295         len = MIN(data->length,sizeof(drivername)-1);
1296         strncpy(drivername, (const char *)data->data, len);
1297
1298         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1299
1300         /* Iterate the printer list */
1301
1302         for (snum=0; snum<n_services; snum++)
1303         {
1304                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1305                 {
1306                         WERROR result;
1307                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1308
1309                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1310                         if (!W_ERROR_IS_OK(result))
1311                                 continue;
1312
1313                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1314                         {
1315                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1316
1317                                 /* all we care about currently is the change_id */
1318
1319                                 result = mod_a_printer(printer, 2);
1320                                 if (!W_ERROR_IS_OK(result)) {
1321                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1322                                                 win_errstr(result)));
1323                                 }
1324                         }
1325
1326                         free_a_printer(&printer, 2);
1327                 }
1328         }
1329
1330         /* all done */
1331 }
1332
1333 /********************************************************************
1334  Update the cache for all printq's with a registered client
1335  connection
1336  ********************************************************************/
1337
1338 void update_monitored_printq_cache( void )
1339 {
1340         Printer_entry *printer = printers_list;
1341         int snum;
1342
1343         /* loop through all printers and update the cache where
1344            client_connected == true */
1345         while ( printer )
1346         {
1347                 if ( (printer->printer_type == SPLHND_PRINTER)
1348                         && printer->notify.client_connected )
1349                 {
1350                         snum = print_queue_snum(printer->sharename);
1351                         print_queue_status( snum, NULL, NULL );
1352                 }
1353
1354                 printer = printer->next;
1355         }
1356
1357         return;
1358 }
1359
1360 /****************************************************************
1361  _spoolss_OpenPrinter
1362 ****************************************************************/
1363
1364 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1365                             struct spoolss_OpenPrinter *r)
1366 {
1367         struct spoolss_OpenPrinterEx e;
1368         WERROR werr;
1369
1370         ZERO_STRUCT(e.in.userlevel);
1371
1372         e.in.printername        = r->in.printername;
1373         e.in.datatype           = r->in.datatype;
1374         e.in.devmode_ctr        = r->in.devmode_ctr;
1375         e.in.access_mask        = r->in.access_mask;
1376         e.in.level              = 0;
1377
1378         e.out.handle            = r->out.handle;
1379
1380         werr = _spoolss_OpenPrinterEx(p, &e);
1381
1382         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1383                 /* OpenPrinterEx returns this for a bad
1384                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1385                  * instead.
1386                  */
1387                 werr = WERR_INVALID_PRINTER_NAME;
1388         }
1389
1390         return werr;
1391 }
1392
1393 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1394                               struct spoolss_DeviceMode *orig,
1395                               struct spoolss_DeviceMode **dest)
1396 {
1397         struct spoolss_DeviceMode *dm;
1398
1399         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1400         if (!dm) {
1401                 return WERR_NOMEM;
1402         }
1403
1404         /* copy all values, then duplicate strings and structs */
1405         *dm = *orig;
1406
1407         dm->devicename = talloc_strdup(dm, orig->devicename);
1408         if (!dm->devicename) {
1409                 return WERR_NOMEM;
1410         }
1411         dm->formname = talloc_strdup(dm, orig->formname);
1412         if (!dm->formname) {
1413                 return WERR_NOMEM;
1414         }
1415         if (orig->driverextra_data.data) {
1416                 dm->driverextra_data.data =
1417                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1418                                         orig->driverextra_data.length);
1419                 if (!dm->driverextra_data.data) {
1420                         return WERR_NOMEM;
1421                 }
1422         }
1423
1424         *dest = dm;
1425         return WERR_OK;
1426 }
1427
1428 /****************************************************************
1429  _spoolss_OpenPrinterEx
1430 ****************************************************************/
1431
1432 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1433                               struct spoolss_OpenPrinterEx *r)
1434 {
1435         int snum;
1436         Printer_entry *Printer=NULL;
1437
1438         if (!r->in.printername) {
1439                 return WERR_INVALID_PARAM;
1440         }
1441
1442         /* some sanity check because you can open a printer or a print server */
1443         /* aka: \\server\printer or \\server */
1444
1445         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1446
1447         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1448                 ZERO_STRUCTP(r->out.handle);
1449                 return WERR_INVALID_PARAM;
1450         }
1451
1452         Printer = find_printer_index_by_hnd(p, r->out.handle);
1453         if ( !Printer ) {
1454                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1455                         "handle we created for printer %s\n", r->in.printername));
1456                 close_printer_handle(p, r->out.handle);
1457                 ZERO_STRUCTP(r->out.handle);
1458                 return WERR_INVALID_PARAM;
1459         }
1460
1461         /*
1462          * First case: the user is opening the print server:
1463          *
1464          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1465          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1466          *
1467          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1468          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1469          * or if the user is listed in the smb.conf printer admin parameter.
1470          *
1471          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1472          * client view printer folder, but does not show the MSAPW.
1473          *
1474          * Note: this test needs code to check access rights here too. Jeremy
1475          * could you look at this?
1476          *
1477          * Second case: the user is opening a printer:
1478          * NT doesn't let us connect to a printer if the connecting user
1479          * doesn't have print permission.
1480          *
1481          * Third case: user is opening a Port Monitor
1482          * access checks same as opening a handle to the print server.
1483          */
1484
1485         switch (Printer->printer_type )
1486         {
1487         case SPLHND_SERVER:
1488         case SPLHND_PORTMON_TCP:
1489         case SPLHND_PORTMON_LOCAL:
1490                 /* Printserver handles use global struct... */
1491
1492                 snum = -1;
1493
1494                 /* Map standard access rights to object specific access rights */
1495
1496                 se_map_standard(&r->in.access_mask,
1497                                 &printserver_std_mapping);
1498
1499                 /* Deny any object specific bits that don't apply to print
1500                    servers (i.e printer and job specific bits) */
1501
1502                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1503
1504                 if (r->in.access_mask &
1505                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1506                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1507                         close_printer_handle(p, r->out.handle);
1508                         ZERO_STRUCTP(r->out.handle);
1509                         return WERR_ACCESS_DENIED;
1510                 }
1511
1512                 /* Allow admin access */
1513
1514                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1515                 {
1516                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1517
1518                         if (!lp_ms_add_printer_wizard()) {
1519                                 close_printer_handle(p, r->out.handle);
1520                                 ZERO_STRUCTP(r->out.handle);
1521                                 return WERR_ACCESS_DENIED;
1522                         }
1523
1524                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1525                            and not a printer admin, then fail */
1526
1527                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1528                             !user_has_privileges(p->server_info->ptok,
1529                                                  &se_printop ) &&
1530                             !token_contains_name_in_list(
1531                                     uidtoname(p->server_info->utok.uid),
1532                                     p->server_info->info3->base.domain.string,
1533                                     NULL,
1534                                     p->server_info->ptok,
1535                                     lp_printer_admin(snum))) {
1536                                 close_printer_handle(p, r->out.handle);
1537                                 ZERO_STRUCTP(r->out.handle);
1538                                 return WERR_ACCESS_DENIED;
1539                         }
1540
1541                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1542                 }
1543                 else
1544                 {
1545                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1546                 }
1547
1548                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1549                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1550
1551                 /* We fall through to return WERR_OK */
1552                 break;
1553
1554         case SPLHND_PRINTER:
1555                 /* NT doesn't let us connect to a printer if the connecting user
1556                    doesn't have print permission.  */
1557
1558                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1559                         close_printer_handle(p, r->out.handle);
1560                         ZERO_STRUCTP(r->out.handle);
1561                         return WERR_BADFID;
1562                 }
1563
1564                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1565                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1566                 }
1567
1568                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1569
1570                 /* map an empty access mask to the minimum access mask */
1571                 if (r->in.access_mask == 0x0)
1572                         r->in.access_mask = PRINTER_ACCESS_USE;
1573
1574                 /*
1575                  * If we are not serving the printer driver for this printer,
1576                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1577                  * will keep NT clients happy  --jerry
1578                  */
1579
1580                 if (lp_use_client_driver(snum)
1581                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1582                 {
1583                         r->in.access_mask = PRINTER_ACCESS_USE;
1584                 }
1585
1586                 /* check smb.conf parameters and the the sec_desc */
1587
1588                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1589                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1590                         ZERO_STRUCTP(r->out.handle);
1591                         return WERR_ACCESS_DENIED;
1592                 }
1593
1594                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1595                                    p->server_info->ptok, snum) ||
1596                     !print_access_check(p->server_info, snum,
1597                                         r->in.access_mask)) {
1598                         DEBUG(3, ("access DENIED for printer open\n"));
1599                         close_printer_handle(p, r->out.handle);
1600                         ZERO_STRUCTP(r->out.handle);
1601                         return WERR_ACCESS_DENIED;
1602                 }
1603
1604                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1605                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1606                         close_printer_handle(p, r->out.handle);
1607                         ZERO_STRUCTP(r->out.handle);
1608                         return WERR_ACCESS_DENIED;
1609                 }
1610
1611                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1612                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1613                 else
1614                         r->in.access_mask = PRINTER_ACCESS_USE;
1615
1616                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1617                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1618
1619                 break;
1620
1621         default:
1622                 /* sanity check to prevent programmer error */
1623                 ZERO_STRUCTP(r->out.handle);
1624                 return WERR_BADFID;
1625         }
1626
1627         Printer->access_granted = r->in.access_mask;
1628
1629         /*
1630          * If the client sent a devmode in the OpenPrinter() call, then
1631          * save it here in case we get a job submission on this handle
1632          */
1633
1634          if ((Printer->printer_type != SPLHND_SERVER) &&
1635              r->in.devmode_ctr.devmode) {
1636                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1637                                 &Printer->devmode);
1638          }
1639
1640 #if 0   /* JERRY -- I'm doubtful this is really effective */
1641         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1642            optimization in Windows 2000 clients  --jerry */
1643
1644         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1645                 && (RA_WIN2K == get_remote_arch()) )
1646         {
1647                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1648                 sys_usleep( 500000 );
1649         }
1650 #endif
1651
1652         return WERR_OK;
1653 }
1654
1655 /****************************************************************************
1656 ****************************************************************************/
1657
1658 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1659                                               NT_PRINTER_INFO_LEVEL_2 *d)
1660 {
1661         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1662
1663         if (!r || !d) {
1664                 return false;
1665         }
1666
1667         d->attributes           = r->attributes;
1668         d->priority             = r->priority;
1669         d->default_priority     = r->defaultpriority;
1670         d->starttime            = r->starttime;
1671         d->untiltime            = r->untiltime;
1672         d->status               = r->status;
1673         d->cjobs                = r->cjobs;
1674
1675         fstrcpy(d->servername,  r->servername);
1676         fstrcpy(d->printername, r->printername);
1677         fstrcpy(d->sharename,   r->sharename);
1678         fstrcpy(d->portname,    r->portname);
1679         fstrcpy(d->drivername,  r->drivername);
1680         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1681         fstrcpy(d->location,    r->location);
1682         fstrcpy(d->sepfile,     r->sepfile);
1683         fstrcpy(d->printprocessor, r->printprocessor);
1684         fstrcpy(d->datatype,    r->datatype);
1685         fstrcpy(d->parameters,  r->parameters);
1686
1687         return true;
1688 }
1689
1690 /****************************************************************************
1691 ****************************************************************************/
1692
1693 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1694                                  NT_PRINTER_INFO_LEVEL *printer)
1695 {
1696         bool ret;
1697
1698         switch (info_ctr->level) {
1699         case 2:
1700                 /* allocate memory if needed.  Messy because
1701                    convert_printer_info is used to update an existing
1702                    printer or build a new one */
1703
1704                 if (!printer->info_2) {
1705                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1706                         if (!printer->info_2) {
1707                                 DEBUG(0,("convert_printer_info: "
1708                                         "talloc() failed!\n"));
1709                                 return false;
1710                         }
1711                 }
1712
1713                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1714                                                         printer->info_2);
1715                 printer->info_2->setuptime = time(NULL);
1716                 return ret;
1717         }
1718
1719         return false;
1720 }
1721
1722 /****************************************************************
1723  _spoolss_ClosePrinter
1724 ****************************************************************/
1725
1726 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1727                              struct spoolss_ClosePrinter *r)
1728 {
1729         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1730
1731         if (Printer && Printer->document_started) {
1732                 struct spoolss_EndDocPrinter e;
1733
1734                 e.in.handle = r->in.handle;
1735
1736                 _spoolss_EndDocPrinter(p, &e);
1737         }
1738
1739         if (!close_printer_handle(p, r->in.handle))
1740                 return WERR_BADFID;
1741
1742         /* clear the returned printer handle.  Observed behavior
1743            from Win2k server.  Don't think this really matters.
1744            Previous code just copied the value of the closed
1745            handle.    --jerry */
1746
1747         ZERO_STRUCTP(r->out.handle);
1748
1749         return WERR_OK;
1750 }
1751
1752 /****************************************************************
1753  _spoolss_DeletePrinter
1754 ****************************************************************/
1755
1756 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1757                               struct spoolss_DeletePrinter *r)
1758 {
1759         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1760         WERROR result;
1761
1762         if (Printer && Printer->document_started) {
1763                 struct spoolss_EndDocPrinter e;
1764
1765                 e.in.handle = r->in.handle;
1766
1767                 _spoolss_EndDocPrinter(p, &e);
1768         }
1769
1770         result = delete_printer_handle(p, r->in.handle);
1771
1772         update_c_setprinter(false);
1773
1774         return result;
1775 }
1776
1777 /*******************************************************************
1778  * static function to lookup the version id corresponding to an
1779  * long architecture string
1780  ******************************************************************/
1781
1782 static const struct print_architecture_table_node archi_table[]= {
1783
1784         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1785         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1786         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1787         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1788         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1789         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1790         {"Windows x64",          SPL_ARCH_X64,          3 },
1791         {NULL,                   "",            -1 }
1792 };
1793
1794 static int get_version_id(const char *arch)
1795 {
1796         int i;
1797
1798         for (i=0; archi_table[i].long_archi != NULL; i++)
1799         {
1800                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1801                         return (archi_table[i].version);
1802         }
1803
1804         return -1;
1805 }
1806
1807 /****************************************************************
1808  _spoolss_DeletePrinterDriver
1809 ****************************************************************/
1810
1811 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1812                                     struct spoolss_DeletePrinterDriver *r)
1813 {
1814
1815         struct spoolss_DriverInfo8 *info = NULL;
1816         struct spoolss_DriverInfo8 *info_win2k = NULL;
1817         int                             version;
1818         WERROR                          status;
1819         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1820         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1821
1822         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1823            and not a printer admin, then fail */
1824
1825         if ( (p->server_info->utok.uid != sec_initial_uid())
1826                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1827                 && !token_contains_name_in_list(
1828                         uidtoname(p->server_info->utok.uid),
1829                         p->server_info->info3->base.domain.string,
1830                         NULL,
1831                         p->server_info->ptok,
1832                         lp_printer_admin(-1)) )
1833         {
1834                 return WERR_ACCESS_DENIED;
1835         }
1836
1837         /* check that we have a valid driver name first */
1838
1839         if ((version = get_version_id(r->in.architecture)) == -1)
1840                 return WERR_INVALID_ENVIRONMENT;
1841
1842         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1843                                                 r->in.architecture,
1844                                                 version)))
1845         {
1846                 /* try for Win2k driver if "Windows NT x86" */
1847
1848                 if ( version == 2 ) {
1849                         version = 3;
1850                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1851                                                                 &info,
1852                                                                 r->in.driver,
1853                                                                 r->in.architecture,
1854                                                                 version))) {
1855                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1856                                 goto done;
1857                         }
1858                 }
1859                 /* otherwise it was a failure */
1860                 else {
1861                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1862                         goto done;
1863                 }
1864
1865         }
1866
1867         if (printer_driver_in_use(info)) {
1868                 status = WERR_PRINTER_DRIVER_IN_USE;
1869                 goto done;
1870         }
1871
1872         if ( version == 2 )
1873         {
1874                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1875                                                        &info_win2k,
1876                                                        r->in.driver,
1877                                                        r->in.architecture, 3)))
1878                 {
1879                         /* if we get to here, we now have 2 driver info structures to remove */
1880                         /* remove the Win2k driver first*/
1881
1882                         status_win2k = delete_printer_driver(
1883                                 p, info_win2k, 3, false);
1884                         free_a_printer_driver(info_win2k);
1885
1886                         /* this should not have failed---if it did, report to client */
1887                         if ( !W_ERROR_IS_OK(status_win2k) )
1888                         {
1889                                 status = status_win2k;
1890                                 goto done;
1891                         }
1892                 }
1893         }
1894
1895         status = delete_printer_driver(p, info, version, false);
1896
1897         /* if at least one of the deletes succeeded return OK */
1898
1899         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1900                 status = WERR_OK;
1901
1902 done:
1903         free_a_printer_driver(info);
1904
1905         return status;
1906 }
1907
1908 /****************************************************************
1909  _spoolss_DeletePrinterDriverEx
1910 ****************************************************************/
1911
1912 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1913                                       struct spoolss_DeletePrinterDriverEx *r)
1914 {
1915         struct spoolss_DriverInfo8      *info = NULL;
1916         struct spoolss_DriverInfo8      *info_win2k = NULL;
1917         int                             version;
1918         bool                            delete_files;
1919         WERROR                          status;
1920         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1921         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1922
1923         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1924            and not a printer admin, then fail */
1925
1926         if ( (p->server_info->utok.uid != sec_initial_uid())
1927                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1928                 && !token_contains_name_in_list(
1929                         uidtoname(p->server_info->utok.uid),
1930                         p->server_info->info3->base.domain.string,
1931                         NULL,
1932                         p->server_info->ptok, lp_printer_admin(-1)) )
1933         {
1934                 return WERR_ACCESS_DENIED;
1935         }
1936
1937         /* check that we have a valid driver name first */
1938         if ((version = get_version_id(r->in.architecture)) == -1) {
1939                 /* this is what NT returns */
1940                 return WERR_INVALID_ENVIRONMENT;
1941         }
1942
1943         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1944                 version = r->in.version;
1945
1946         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1947                                       r->in.architecture, version);
1948
1949         if ( !W_ERROR_IS_OK(status) )
1950         {
1951                 /*
1952                  * if the client asked for a specific version,
1953                  * or this is something other than Windows NT x86,
1954                  * then we've failed
1955                  */
1956
1957                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1958                         goto done;
1959
1960                 /* try for Win2k driver if "Windows NT x86" */
1961
1962                 version = 3;
1963                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1964                                                         r->in.architecture,
1965                                                         version))) {
1966                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1967                         goto done;
1968                 }
1969         }
1970
1971         if (printer_driver_in_use(info)) {
1972                 status = WERR_PRINTER_DRIVER_IN_USE;
1973                 goto done;
1974         }
1975
1976         /*
1977          * we have a couple of cases to consider.
1978          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
1979          *     then the delete should fail if **any** files overlap with
1980          *     other drivers
1981          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1982          *     non-overlapping files
1983          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1984          *     is set, the do not delete any files
1985          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1986          */
1987
1988         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1989
1990         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1991
1992         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
1993                 /* no idea of the correct error here */
1994                 status = WERR_ACCESS_DENIED;
1995                 goto done;
1996         }
1997
1998
1999         /* also check for W32X86/3 if necessary; maybe we already have? */
2000
2001         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2002                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2003                                                        r->in.driver,
2004                                                        r->in.architecture, 3)))
2005                 {
2006
2007                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2008                                 /* no idea of the correct error here */
2009                                 free_a_printer_driver(info_win2k);
2010                                 status = WERR_ACCESS_DENIED;
2011                                 goto done;
2012                         }
2013
2014                         /* if we get to here, we now have 2 driver info structures to remove */
2015                         /* remove the Win2k driver first*/
2016
2017                         status_win2k = delete_printer_driver(
2018                                 p, info_win2k, 3, delete_files);
2019                         free_a_printer_driver(info_win2k);
2020
2021                         /* this should not have failed---if it did, report to client */
2022
2023                         if ( !W_ERROR_IS_OK(status_win2k) )
2024                                 goto done;
2025                 }
2026         }
2027
2028         status = delete_printer_driver(p, info, version, delete_files);
2029
2030         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2031                 status = WERR_OK;
2032 done:
2033         free_a_printer_driver(info);
2034
2035         return status;
2036 }
2037
2038
2039 /****************************************************************************
2040  Internal routine for removing printerdata
2041  ***************************************************************************/
2042
2043 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2044 {
2045         return delete_printer_data( printer->info_2, key, value );
2046 }
2047
2048 /****************************************************************************
2049  Internal routine for storing printerdata
2050  ***************************************************************************/
2051
2052 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2053                           const char *key, const char *value,
2054                           uint32_t type, uint8_t *data, int real_len)
2055 {
2056         /* the registry objects enforce uniqueness based on value name */
2057
2058         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2059 }
2060
2061 /********************************************************************
2062  GetPrinterData on a printer server Handle.
2063 ********************************************************************/
2064
2065 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2066                                             const char *value,
2067                                             enum winreg_Type *type,
2068                                             union spoolss_PrinterData *data)
2069 {
2070         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2071
2072         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2073                 *type = REG_DWORD;
2074                 data->value = 0x00;
2075                 return WERR_OK;
2076         }
2077
2078         if (!StrCaseCmp(value, "BeepEnabled")) {
2079                 *type = REG_DWORD;
2080                 data->value = 0x00;
2081                 return WERR_OK;
2082         }
2083
2084         if (!StrCaseCmp(value, "EventLog")) {
2085                 *type = REG_DWORD;
2086                 /* formally was 0x1b */
2087                 data->value = 0x00;
2088                 return WERR_OK;
2089         }
2090
2091         if (!StrCaseCmp(value, "NetPopup")) {
2092                 *type = REG_DWORD;
2093                 data->value = 0x00;
2094                 return WERR_OK;
2095         }
2096
2097         if (!StrCaseCmp(value, "MajorVersion")) {
2098                 *type = REG_DWORD;
2099
2100                 /* Windows NT 4.0 seems to not allow uploading of drivers
2101                    to a server that reports 0x3 as the MajorVersion.
2102                    need to investigate more how Win2k gets around this .
2103                    -- jerry */
2104
2105                 if (RA_WINNT == get_remote_arch()) {
2106                         data->value = 0x02;
2107                 } else {
2108                         data->value = 0x03;
2109                 }
2110
2111                 return WERR_OK;
2112         }
2113
2114         if (!StrCaseCmp(value, "MinorVersion")) {
2115                 *type = REG_DWORD;
2116                 data->value = 0x00;
2117                 return WERR_OK;
2118         }
2119
2120         /* REG_BINARY
2121          *  uint32_t size        = 0x114
2122          *  uint32_t major       = 5
2123          *  uint32_t minor       = [0|1]
2124          *  uint32_t build       = [2195|2600]
2125          *  extra unicode string = e.g. "Service Pack 3"
2126          */
2127         if (!StrCaseCmp(value, "OSVersion")) {
2128                 DATA_BLOB blob;
2129                 enum ndr_err_code ndr_err;
2130                 struct spoolss_OSVersion os;
2131
2132                 os.major                = 5;    /* Windows 2000 == 5.0 */
2133                 os.minor                = 0;
2134                 os.build                = 2195; /* build */
2135                 os.extra_string         = "";   /* leave extra string empty */
2136
2137                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2138                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2139                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2140                         return WERR_GENERAL_FAILURE;
2141                 }
2142
2143                 *type = REG_BINARY;
2144                 data->binary = blob;
2145
2146                 return WERR_OK;
2147         }
2148
2149
2150         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2151                 *type = REG_SZ;
2152
2153                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2154                 W_ERROR_HAVE_NO_MEMORY(data->string);
2155
2156                 return WERR_OK;
2157         }
2158
2159         if (!StrCaseCmp(value, "Architecture")) {
2160                 *type = REG_SZ;
2161                 data->string = talloc_strdup(mem_ctx,
2162                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2163                 W_ERROR_HAVE_NO_MEMORY(data->string);
2164
2165                 return WERR_OK;
2166         }
2167
2168         if (!StrCaseCmp(value, "DsPresent")) {
2169                 *type = REG_DWORD;
2170
2171                 /* only show the publish check box if we are a
2172                    member of a AD domain */
2173
2174                 if (lp_security() == SEC_ADS) {
2175                         data->value = 0x01;
2176                 } else {
2177                         data->value = 0x00;
2178                 }
2179                 return WERR_OK;
2180         }
2181
2182         if (!StrCaseCmp(value, "DNSMachineName")) {
2183                 const char *hostname = get_mydnsfullname();
2184
2185                 if (!hostname) {
2186                         return WERR_BADFILE;
2187                 }
2188
2189                 *type = REG_SZ;
2190                 data->string = talloc_strdup(mem_ctx, hostname);
2191                 W_ERROR_HAVE_NO_MEMORY(data->string);
2192
2193                 return WERR_OK;
2194         }
2195
2196         *type = REG_NONE;
2197
2198         return WERR_INVALID_PARAM;
2199 }
2200
2201 /****************************************************************
2202  _spoolss_GetPrinterData
2203 ****************************************************************/
2204
2205 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2206                                struct spoolss_GetPrinterData *r)
2207 {
2208         struct spoolss_GetPrinterDataEx r2;
2209
2210         r2.in.handle            = r->in.handle;
2211         r2.in.key_name          = "PrinterDriverData";
2212         r2.in.value_name        = r->in.value_name;
2213         r2.in.offered           = r->in.offered;
2214         r2.out.type             = r->out.type;
2215         r2.out.data             = r->out.data;
2216         r2.out.needed           = r->out.needed;
2217
2218         return _spoolss_GetPrinterDataEx(p, &r2);
2219 }
2220
2221 /*********************************************************
2222  Connect to the client machine.
2223 **********************************************************/
2224
2225 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2226                         struct sockaddr_storage *client_ss, const char *remote_machine)
2227 {
2228         NTSTATUS ret;
2229         struct cli_state *the_cli;
2230         struct sockaddr_storage rm_addr;
2231         char addr[INET6_ADDRSTRLEN];
2232
2233         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2234                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2235                         remote_machine));
2236                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2237                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2238                         return false;
2239                 }
2240                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2241         } else {
2242                 rm_addr = *client_ss;
2243                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2244                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2245                         addr));
2246         }
2247
2248         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2249                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2250                         addr));
2251                 return false;
2252         }
2253
2254         /* setup the connection */
2255         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2256                 &rm_addr, 0, "IPC$", "IPC",
2257                 "", /* username */
2258                 "", /* domain */
2259                 "", /* password */
2260                 0, lp_client_signing(), NULL );
2261
2262         if ( !NT_STATUS_IS_OK( ret ) ) {
2263                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2264                         remote_machine ));
2265                 return false;
2266         }
2267
2268         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2269                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2270                 cli_shutdown(the_cli);
2271                 return false;
2272         }
2273
2274         /*
2275          * Ok - we have an anonymous connection to the IPC$ share.
2276          * Now start the NT Domain stuff :-).
2277          */
2278
2279         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2280         if (!NT_STATUS_IS_OK(ret)) {
2281                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2282                         remote_machine, nt_errstr(ret)));
2283                 cli_shutdown(the_cli);
2284                 return false;
2285         }
2286
2287         return true;
2288 }
2289
2290 /***************************************************************************
2291  Connect to the client.
2292 ****************************************************************************/
2293
2294 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2295                                         uint32_t localprinter, uint32_t type,
2296                                         struct policy_handle *handle,
2297                                         struct sockaddr_storage *client_ss)
2298 {
2299         WERROR result;
2300         NTSTATUS status;
2301
2302         /*
2303          * If it's the first connection, contact the client
2304          * and connect to the IPC$ share anonymously
2305          */
2306         if (smb_connections==0) {
2307                 fstring unix_printer;
2308
2309                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2310
2311                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2312                         return false;
2313
2314                 messaging_register(smbd_messaging_context(), NULL,
2315                                    MSG_PRINTER_NOTIFY2,
2316                                    receive_notify2_message_list);
2317                 /* Tell the connections db we're now interested in printer
2318                  * notify messages. */
2319                 serverid_register_msg_flags(
2320                         messaging_server_id(smbd_messaging_context()),
2321                         true, FLAG_MSG_PRINT_NOTIFY);
2322         }
2323
2324         /*
2325          * Tell the specific printing tdb we want messages for this printer
2326          * by registering our PID.
2327          */
2328
2329         if (!print_notify_register_pid(snum))
2330                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2331
2332         smb_connections++;
2333
2334         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2335                                                  printer,
2336                                                  localprinter,
2337                                                  type,
2338                                                  0,
2339                                                  NULL,
2340                                                  handle,
2341                                                  &result);
2342         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2343                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2344                         win_errstr(result)));
2345
2346         return (W_ERROR_IS_OK(result));
2347 }
2348
2349 /****************************************************************
2350  ****************************************************************/
2351
2352 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2353                                                              const struct spoolss_NotifyOption *r)
2354 {
2355         struct spoolss_NotifyOption *option;
2356         uint32_t i,k;
2357
2358         if (!r) {
2359                 return NULL;
2360         }
2361
2362         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2363         if (!option) {
2364                 return NULL;
2365         }
2366
2367         *option = *r;
2368
2369         if (!option->count) {
2370                 return option;
2371         }
2372
2373         option->types = talloc_zero_array(option,
2374                 struct spoolss_NotifyOptionType, option->count);
2375         if (!option->types) {
2376                 talloc_free(option);
2377                 return NULL;
2378         }
2379
2380         for (i=0; i < option->count; i++) {
2381                 option->types[i] = r->types[i];
2382
2383                 if (option->types[i].count) {
2384                         option->types[i].fields = talloc_zero_array(option,
2385                                 union spoolss_Field, option->types[i].count);
2386                         if (!option->types[i].fields) {
2387                                 talloc_free(option);
2388                                 return NULL;
2389                         }
2390                         for (k=0; k<option->types[i].count; k++) {
2391                                 option->types[i].fields[k] =
2392                                         r->types[i].fields[k];
2393                         }
2394                 }
2395         }
2396
2397         return option;
2398 }
2399
2400 /****************************************************************
2401  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2402  *
2403  * before replying OK: status=0 a rpc call is made to the workstation
2404  * asking ReplyOpenPrinter
2405  *
2406  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2407  * called from api_spoolss_rffpcnex
2408 ****************************************************************/
2409
2410 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2411                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2412 {
2413         int snum = -1;
2414         struct spoolss_NotifyOption *option = r->in.notify_options;
2415         struct sockaddr_storage client_ss;
2416
2417         /* store the notify value in the printer struct */
2418
2419         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2420
2421         if (!Printer) {
2422                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2423                         "Invalid handle (%s:%u:%u).\n",
2424                         OUR_HANDLE(r->in.handle)));
2425                 return WERR_BADFID;
2426         }
2427
2428         Printer->notify.flags           = r->in.flags;
2429         Printer->notify.options         = r->in.options;
2430         Printer->notify.printerlocal    = r->in.printer_local;
2431
2432         TALLOC_FREE(Printer->notify.option);
2433         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2434
2435         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2436
2437         /* Connect to the client machine and send a ReplyOpenPrinter */
2438
2439         if ( Printer->printer_type == SPLHND_SERVER)
2440                 snum = -1;
2441         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2442                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2443                 return WERR_BADFID;
2444
2445         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2446                 "client_address is %s\n", p->client_address));
2447
2448         if (!interpret_string_addr(&client_ss, p->client_address,
2449                                    AI_NUMERICHOST)) {
2450                 return WERR_SERVER_UNAVAILABLE;
2451         }
2452
2453         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2454                                         Printer->notify.printerlocal, 1,
2455                                         &Printer->notify.client_hnd, &client_ss))
2456                 return WERR_SERVER_UNAVAILABLE;
2457
2458         Printer->notify.client_connected = true;
2459
2460         return WERR_OK;
2461 }
2462
2463 /*******************************************************************
2464  * fill a notify_info_data with the servername
2465  ********************************************************************/
2466
2467 static void spoolss_notify_server_name(int snum,
2468                                        struct spoolss_Notify *data,
2469                                        print_queue_struct *queue,
2470                                        NT_PRINTER_INFO_LEVEL *printer,
2471                                        TALLOC_CTX *mem_ctx)
2472 {
2473         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2474 }
2475
2476 /*******************************************************************
2477  * fill a notify_info_data with the printername (not including the servername).
2478  ********************************************************************/
2479
2480 static void spoolss_notify_printer_name(int snum,
2481                                         struct spoolss_Notify *data,
2482                                         print_queue_struct *queue,
2483                                         NT_PRINTER_INFO_LEVEL *printer,
2484                                         TALLOC_CTX *mem_ctx)
2485 {
2486         /* the notify name should not contain the \\server\ part */
2487         char *p = strrchr(printer->info_2->printername, '\\');
2488
2489         if (!p) {
2490                 p = printer->info_2->printername;
2491         } else {
2492                 p++;
2493         }
2494
2495         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2496 }
2497
2498 /*******************************************************************
2499  * fill a notify_info_data with the servicename
2500  ********************************************************************/
2501
2502 static void spoolss_notify_share_name(int snum,
2503                                       struct spoolss_Notify *data,
2504                                       print_queue_struct *queue,
2505                                       NT_PRINTER_INFO_LEVEL *printer,
2506                                       TALLOC_CTX *mem_ctx)
2507 {
2508         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2509 }
2510
2511 /*******************************************************************
2512  * fill a notify_info_data with the port name
2513  ********************************************************************/
2514
2515 static void spoolss_notify_port_name(int snum,
2516                                      struct spoolss_Notify *data,
2517                                      print_queue_struct *queue,
2518                                      NT_PRINTER_INFO_LEVEL *printer,
2519                                      TALLOC_CTX *mem_ctx)
2520 {
2521         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2522 }
2523
2524 /*******************************************************************
2525  * fill a notify_info_data with the printername
2526  * but it doesn't exist, have to see what to do
2527  ********************************************************************/
2528
2529 static void spoolss_notify_driver_name(int snum,
2530                                        struct spoolss_Notify *data,
2531                                        print_queue_struct *queue,
2532                                        NT_PRINTER_INFO_LEVEL *printer,
2533                                        TALLOC_CTX *mem_ctx)
2534 {
2535         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2536 }
2537
2538 /*******************************************************************
2539  * fill a notify_info_data with the comment
2540  ********************************************************************/
2541
2542 static void spoolss_notify_comment(int snum,
2543                                    struct spoolss_Notify *data,
2544                                    print_queue_struct *queue,
2545                                    NT_PRINTER_INFO_LEVEL *printer,
2546                                    TALLOC_CTX *mem_ctx)
2547 {
2548         char *p;
2549
2550         if (*printer->info_2->comment == '\0') {
2551                 p = lp_comment(snum);
2552         } else {
2553                 p = printer->info_2->comment;
2554         }
2555
2556         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2557 }
2558
2559 /*******************************************************************
2560  * fill a notify_info_data with the comment
2561  * location = "Room 1, floor 2, building 3"
2562  ********************************************************************/
2563
2564 static void spoolss_notify_location(int snum,
2565                                     struct spoolss_Notify *data,
2566                                     print_queue_struct *queue,
2567                                     NT_PRINTER_INFO_LEVEL *printer,
2568                                     TALLOC_CTX *mem_ctx)
2569 {
2570         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2571 }
2572
2573 /*******************************************************************
2574  * fill a notify_info_data with the device mode
2575  * jfm:xxxx don't to it for know but that's a real problem !!!
2576  ********************************************************************/
2577
2578 static void spoolss_notify_devmode(int snum,
2579                                    struct spoolss_Notify *data,
2580                                    print_queue_struct *queue,
2581                                    NT_PRINTER_INFO_LEVEL *printer,
2582                                    TALLOC_CTX *mem_ctx)
2583 {
2584         /* for a dummy implementation we have to zero the fields */
2585         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2586 }
2587
2588 /*******************************************************************
2589  * fill a notify_info_data with the separator file name
2590  ********************************************************************/
2591
2592 static void spoolss_notify_sepfile(int snum,
2593                                    struct spoolss_Notify *data,
2594                                    print_queue_struct *queue,
2595                                    NT_PRINTER_INFO_LEVEL *printer,
2596                                    TALLOC_CTX *mem_ctx)
2597 {
2598         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2599 }
2600
2601 /*******************************************************************
2602  * fill a notify_info_data with the print processor
2603  * jfm:xxxx return always winprint to indicate we don't do anything to it
2604  ********************************************************************/
2605
2606 static void spoolss_notify_print_processor(int snum,
2607                                            struct spoolss_Notify *data,
2608                                            print_queue_struct *queue,
2609                                            NT_PRINTER_INFO_LEVEL *printer,
2610                                            TALLOC_CTX *mem_ctx)
2611 {
2612         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2613 }
2614
2615 /*******************************************************************
2616  * fill a notify_info_data with the print processor options
2617  * jfm:xxxx send an empty string
2618  ********************************************************************/
2619
2620 static void spoolss_notify_parameters(int snum,
2621                                       struct spoolss_Notify *data,
2622                                       print_queue_struct *queue,
2623                                       NT_PRINTER_INFO_LEVEL *printer,
2624                                       TALLOC_CTX *mem_ctx)
2625 {
2626         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2627 }
2628
2629 /*******************************************************************
2630  * fill a notify_info_data with the data type
2631  * jfm:xxxx always send RAW as data type
2632  ********************************************************************/
2633
2634 static void spoolss_notify_datatype(int snum,
2635                                     struct spoolss_Notify *data,
2636                                     print_queue_struct *queue,
2637                                     NT_PRINTER_INFO_LEVEL *printer,
2638                                     TALLOC_CTX *mem_ctx)
2639 {
2640         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2641 }
2642
2643 /*******************************************************************
2644  * fill a notify_info_data with the security descriptor
2645  * jfm:xxxx send an null pointer to say no security desc
2646  * have to implement security before !
2647  ********************************************************************/
2648
2649 static void spoolss_notify_security_desc(int snum,
2650                                          struct spoolss_Notify *data,
2651                                          print_queue_struct *queue,
2652                                          NT_PRINTER_INFO_LEVEL *printer,
2653                                          TALLOC_CTX *mem_ctx)
2654 {
2655         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2656                                           printer->info_2->secdesc_buf->sd_size,
2657                                           printer->info_2->secdesc_buf->sd);
2658 }
2659
2660 /*******************************************************************
2661  * fill a notify_info_data with the attributes
2662  * jfm:xxxx a samba printer is always shared
2663  ********************************************************************/
2664
2665 static void spoolss_notify_attributes(int snum,
2666                                       struct spoolss_Notify *data,
2667                                       print_queue_struct *queue,
2668                                       NT_PRINTER_INFO_LEVEL *printer,
2669                                       TALLOC_CTX *mem_ctx)
2670 {
2671         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2672 }
2673
2674 /*******************************************************************
2675  * fill a notify_info_data with the priority
2676  ********************************************************************/
2677
2678 static void spoolss_notify_priority(int snum,
2679                                     struct spoolss_Notify *data,
2680                                     print_queue_struct *queue,
2681                                     NT_PRINTER_INFO_LEVEL *printer,
2682                                     TALLOC_CTX *mem_ctx)
2683 {
2684         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2685 }
2686
2687 /*******************************************************************
2688  * fill a notify_info_data with the default priority
2689  ********************************************************************/
2690
2691 static void spoolss_notify_default_priority(int snum,
2692                                             struct spoolss_Notify *data,
2693                                             print_queue_struct *queue,
2694                                             NT_PRINTER_INFO_LEVEL *printer,
2695                                             TALLOC_CTX *mem_ctx)
2696 {
2697         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2698 }
2699
2700 /*******************************************************************
2701  * fill a notify_info_data with the start time
2702  ********************************************************************/
2703
2704 static void spoolss_notify_start_time(int snum,
2705                                       struct spoolss_Notify *data,
2706                                       print_queue_struct *queue,
2707                                       NT_PRINTER_INFO_LEVEL *printer,
2708                                       TALLOC_CTX *mem_ctx)
2709 {
2710         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2711 }
2712
2713 /*******************************************************************
2714  * fill a notify_info_data with the until time
2715  ********************************************************************/
2716
2717 static void spoolss_notify_until_time(int snum,
2718                                       struct spoolss_Notify *data,
2719                                       print_queue_struct *queue,
2720                                       NT_PRINTER_INFO_LEVEL *printer,
2721                                       TALLOC_CTX *mem_ctx)
2722 {
2723         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2724 }
2725
2726 /*******************************************************************
2727  * fill a notify_info_data with the status
2728  ********************************************************************/
2729
2730 static void spoolss_notify_status(int snum,
2731                                   struct spoolss_Notify *data,
2732                                   print_queue_struct *queue,
2733                                   NT_PRINTER_INFO_LEVEL *printer,
2734                                   TALLOC_CTX *mem_ctx)
2735 {
2736         print_status_struct status;
2737
2738         print_queue_length(snum, &status);
2739         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2740 }
2741
2742 /*******************************************************************
2743  * fill a notify_info_data with the number of jobs queued
2744  ********************************************************************/
2745
2746 static void spoolss_notify_cjobs(int snum,
2747                                  struct spoolss_Notify *data,
2748                                  print_queue_struct *queue,
2749                                  NT_PRINTER_INFO_LEVEL *printer,
2750                                  TALLOC_CTX *mem_ctx)
2751 {
2752         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2753 }
2754
2755 /*******************************************************************
2756  * fill a notify_info_data with the average ppm
2757  ********************************************************************/
2758
2759 static void spoolss_notify_average_ppm(int snum,
2760                                        struct spoolss_Notify *data,
2761                                        print_queue_struct *queue,
2762                                        NT_PRINTER_INFO_LEVEL *printer,
2763                                        TALLOC_CTX *mem_ctx)
2764 {
2765         /* always respond 8 pages per minutes */
2766         /* a little hard ! */
2767         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2768 }
2769
2770 /*******************************************************************
2771  * fill a notify_info_data with username
2772  ********************************************************************/
2773
2774 static void spoolss_notify_username(int snum,
2775                                     struct spoolss_Notify *data,
2776                                     print_queue_struct *queue,
2777                                     NT_PRINTER_INFO_LEVEL *printer,
2778                                     TALLOC_CTX *mem_ctx)
2779 {
2780         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2781 }
2782
2783 /*******************************************************************
2784  * fill a notify_info_data with job status
2785  ********************************************************************/
2786
2787 static void spoolss_notify_job_status(int snum,
2788                                       struct spoolss_Notify *data,
2789                                       print_queue_struct *queue,
2790                                       NT_PRINTER_INFO_LEVEL *printer,
2791                                       TALLOC_CTX *mem_ctx)
2792 {
2793         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2794 }
2795
2796 /*******************************************************************
2797  * fill a notify_info_data with job name
2798  ********************************************************************/
2799
2800 static void spoolss_notify_job_name(int snum,
2801                                     struct spoolss_Notify *data,
2802                                     print_queue_struct *queue,
2803                                     NT_PRINTER_INFO_LEVEL *printer,
2804                                     TALLOC_CTX *mem_ctx)
2805 {
2806         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2807 }
2808
2809 /*******************************************************************
2810  * fill a notify_info_data with job status
2811  ********************************************************************/
2812
2813 static void spoolss_notify_job_status_string(int snum,
2814                                              struct spoolss_Notify *data,
2815                                              print_queue_struct *queue,
2816                                              NT_PRINTER_INFO_LEVEL *printer,
2817                                              TALLOC_CTX *mem_ctx)
2818 {
2819         /*
2820          * Now we're returning job status codes we just return a "" here. JRA.
2821          */
2822
2823         const char *p = "";
2824
2825 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2826         p = "unknown";
2827
2828         switch (queue->status) {
2829         case LPQ_QUEUED:
2830                 p = "Queued";
2831                 break;
2832         case LPQ_PAUSED:
2833                 p = "";    /* NT provides the paused string */
2834                 break;
2835         case LPQ_SPOOLING:
2836                 p = "Spooling";
2837                 break;
2838         case LPQ_PRINTING:
2839                 p = "Printing";
2840                 break;
2841         }
2842 #endif /* NO LONGER NEEDED. */
2843
2844         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2845 }
2846
2847 /*******************************************************************
2848  * fill a notify_info_data with job time
2849  ********************************************************************/
2850
2851 static void spoolss_notify_job_time(int snum,
2852                                     struct spoolss_Notify *data,
2853                                     print_queue_struct *queue,
2854                                     NT_PRINTER_INFO_LEVEL *printer,
2855                                     TALLOC_CTX *mem_ctx)
2856 {
2857         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2858 }
2859
2860 /*******************************************************************
2861  * fill a notify_info_data with job size
2862  ********************************************************************/
2863
2864 static void spoolss_notify_job_size(int snum,
2865                                     struct spoolss_Notify *data,
2866                                     print_queue_struct *queue,
2867                                     NT_PRINTER_INFO_LEVEL *printer,
2868                                     TALLOC_CTX *mem_ctx)
2869 {
2870         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2871 }
2872
2873 /*******************************************************************
2874  * fill a notify_info_data with page info
2875  ********************************************************************/
2876 static void spoolss_notify_total_pages(int snum,
2877                                 struct spoolss_Notify *data,
2878                                 print_queue_struct *queue,
2879                                 NT_PRINTER_INFO_LEVEL *printer,
2880                                 TALLOC_CTX *mem_ctx)
2881 {
2882         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with pages printed info.
2887  ********************************************************************/
2888 static void spoolss_notify_pages_printed(int snum,
2889                                 struct spoolss_Notify *data,
2890                                 print_queue_struct *queue,
2891                                 NT_PRINTER_INFO_LEVEL *printer,
2892                                 TALLOC_CTX *mem_ctx)
2893 {
2894         /* Add code when back-end tracks this */
2895         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2896 }
2897
2898 /*******************************************************************
2899  Fill a notify_info_data with job position.
2900  ********************************************************************/
2901
2902 static void spoolss_notify_job_position(int snum,
2903                                         struct spoolss_Notify *data,
2904                                         print_queue_struct *queue,
2905                                         NT_PRINTER_INFO_LEVEL *printer,
2906                                         TALLOC_CTX *mem_ctx)
2907 {
2908         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2909 }
2910
2911 /*******************************************************************
2912  Fill a notify_info_data with submitted time.
2913  ********************************************************************/
2914
2915 static void spoolss_notify_submitted_time(int snum,
2916                                           struct spoolss_Notify *data,
2917                                           print_queue_struct *queue,
2918                                           NT_PRINTER_INFO_LEVEL *printer,
2919                                           TALLOC_CTX *mem_ctx)
2920 {
2921         data->data.string.string = NULL;
2922         data->data.string.size = 0;
2923
2924         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2925                                &data->data.string.string,
2926                                &data->data.string.size);
2927
2928 }
2929
2930 struct s_notify_info_data_table
2931 {
2932         enum spoolss_NotifyType type;
2933         uint16_t field;
2934         const char *name;
2935         enum spoolss_NotifyTable variable_type;
2936         void (*fn) (int snum, struct spoolss_Notify *data,
2937                     print_queue_struct *queue,
2938                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2939 };
2940
2941 /* A table describing the various print notification constants and
2942    whether the notification data is a pointer to a variable sized
2943    buffer, a one value uint32_t or a two value uint32_t. */
2944
2945 static const struct s_notify_info_data_table notify_info_data_table[] =
2946 {
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2949 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
2950 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2951 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2952 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
2953 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
2954 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2955 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
2956 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2957 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2958 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2959 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
2960 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
2961 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2962 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
2963 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2964 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2965 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
2966 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
2967 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
2968 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
2969 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
2970 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2971 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
2972 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2973 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2974 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2975 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2976 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
2977 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
2978 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2979 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2980 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2981 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2982 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2983 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
2984 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
2985 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
2986 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
2987 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2988 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
2989 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
2990 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2991 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2992 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
2993 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
2994 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
2995 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
2996 };
2997
2998 /*******************************************************************
2999  Return the variable_type of info_data structure.
3000 ********************************************************************/
3001
3002 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3003                                                   uint16_t field)
3004 {
3005         int i=0;
3006
3007         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3008                 if ( (notify_info_data_table[i].type == type) &&
3009                      (notify_info_data_table[i].field == field) ) {
3010                         return notify_info_data_table[i].variable_type;
3011                 }
3012         }
3013
3014         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3015
3016         return 0;
3017 }
3018
3019 /****************************************************************************
3020 ****************************************************************************/
3021
3022 static bool search_notify(enum spoolss_NotifyType type,
3023                           uint16_t field,
3024                           int *value)
3025 {
3026         int i;
3027
3028         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3029                 if (notify_info_data_table[i].type == type &&
3030                     notify_info_data_table[i].field == field &&
3031                     notify_info_data_table[i].fn != NULL) {
3032                         *value = i;
3033                         return true;
3034                 }
3035         }
3036
3037         return false;
3038 }
3039
3040 /****************************************************************************
3041 ****************************************************************************/
3042
3043 void construct_info_data(struct spoolss_Notify *info_data,
3044                          enum spoolss_NotifyType type,
3045                          uint16_t field,
3046                          int id)
3047 {
3048         info_data->type                 = type;
3049         info_data->field.field          = field;
3050         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3051         info_data->job_id               = id;
3052 }
3053
3054 /*******************************************************************
3055  *
3056  * fill a notify_info struct with info asked
3057  *
3058  ********************************************************************/
3059
3060 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3061                                           struct spoolss_NotifyInfo *info,
3062                                           int snum,
3063                                           const struct spoolss_NotifyOptionType *option_type,
3064                                           uint32_t id,
3065                                           TALLOC_CTX *mem_ctx)
3066 {
3067         int field_num,j;
3068         enum spoolss_NotifyType type;
3069         uint16_t field;
3070
3071         struct spoolss_Notify *current_data;
3072         NT_PRINTER_INFO_LEVEL *printer = NULL;
3073         print_queue_struct *queue=NULL;
3074
3075         type = option_type->type;
3076
3077         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3078                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3079                 option_type->count, lp_servicename(snum)));
3080
3081         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3082                 return false;
3083
3084         for(field_num=0; field_num < option_type->count; field_num++) {
3085                 field = option_type->fields[field_num].field;
3086
3087                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3088
3089                 if (!search_notify(type, field, &j) )
3090                         continue;
3091
3092                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3093                                                       struct spoolss_Notify,
3094                                                       info->count + 1);
3095                 if (info->notifies == NULL) {
3096                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3097                         free_a_printer(&printer, 2);
3098                         return false;
3099                 }
3100
3101                 current_data = &info->notifies[info->count];
3102
3103                 construct_info_data(current_data, type, field, id);
3104
3105                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3106                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3107
3108                 notify_info_data_table[j].fn(snum, current_data, queue,
3109                                              printer, mem_ctx);
3110
3111                 info->count++;
3112         }
3113
3114         free_a_printer(&printer, 2);
3115         return true;
3116 }
3117
3118 /*******************************************************************
3119  *
3120  * fill a notify_info struct with info asked
3121  *
3122  ********************************************************************/
3123
3124 static bool construct_notify_jobs_info(print_queue_struct *queue,
3125                                        struct spoolss_NotifyInfo *info,
3126                                        NT_PRINTER_INFO_LEVEL *printer,
3127                                        int snum,
3128                                        const struct spoolss_NotifyOptionType *option_type,
3129                                        uint32_t id,
3130                                        TALLOC_CTX *mem_ctx)
3131 {
3132         int field_num,j;
3133         enum spoolss_NotifyType type;
3134         uint16_t field;
3135         struct spoolss_Notify *current_data;
3136
3137         DEBUG(4,("construct_notify_jobs_info\n"));
3138
3139         type = option_type->type;
3140
3141         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3142                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3143                 option_type->count));
3144
3145         for(field_num=0; field_num<option_type->count; field_num++) {
3146                 field = option_type->fields[field_num].field;
3147
3148                 if (!search_notify(type, field, &j) )
3149                         continue;
3150
3151                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3152                                                       struct spoolss_Notify,
3153                                                       info->count + 1);
3154                 if (info->notifies == NULL) {
3155                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3156                         return false;
3157                 }
3158
3159                 current_data=&(info->notifies[info->count]);
3160
3161                 construct_info_data(current_data, type, field, id);
3162                 notify_info_data_table[j].fn(snum, current_data, queue,
3163                                              printer, mem_ctx);
3164                 info->count++;
3165         }
3166
3167         return true;
3168 }
3169
3170 /*
3171  * JFM: The enumeration is not that simple, it's even non obvious.
3172  *
3173  * let's take an example: I want to monitor the PRINTER SERVER for
3174  * the printer's name and the number of jobs currently queued.
3175  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3176  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3177  *
3178  * I have 3 printers on the back of my server.
3179  *
3180  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3181  * structures.
3182  *   Number     Data                    Id
3183  *      1       printer 1 name          1
3184  *      2       printer 1 cjob          1
3185  *      3       printer 2 name          2
3186  *      4       printer 2 cjob          2
3187  *      5       printer 3 name          3
3188  *      6       printer 3 name          3
3189  *
3190  * that's the print server case, the printer case is even worse.
3191  */
3192
3193 /*******************************************************************
3194  *
3195  * enumerate all printers on the printserver
3196  * fill a notify_info struct with info asked
3197  *
3198  ********************************************************************/
3199
3200 static WERROR printserver_notify_info(pipes_struct *p,
3201                                       struct policy_handle *hnd,
3202                                       struct spoolss_NotifyInfo *info,
3203                                       TALLOC_CTX *mem_ctx)
3204 {
3205         int snum;
3206         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3207         int n_services=lp_numservices();
3208         int i;
3209         struct spoolss_NotifyOption *option;
3210         struct spoolss_NotifyOptionType option_type;
3211
3212         DEBUG(4,("printserver_notify_info\n"));
3213
3214         if (!Printer)
3215                 return WERR_BADFID;
3216
3217         option = Printer->notify.option;
3218
3219         info->version   = 2;
3220         info->notifies  = NULL;
3221         info->count     = 0;
3222
3223         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3224            sending a ffpcn() request first */
3225
3226         if ( !option )
3227                 return WERR_BADFID;
3228
3229         for (i=0; i<option->count; i++) {
3230                 option_type = option->types[i];
3231
3232                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3233                         continue;
3234
3235                 for (snum=0; snum<n_services; snum++)
3236                 {
3237                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3238                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3239                 }
3240         }
3241
3242 #if 0
3243         /*
3244          * Debugging information, don't delete.
3245          */
3246
3247         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3248         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3249         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3250
3251         for (i=0; i<info->count; i++) {
3252                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3253                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3254                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3255         }
3256 #endif
3257
3258         return WERR_OK;
3259 }
3260
3261 /*******************************************************************
3262  *
3263  * fill a notify_info struct with info asked
3264  *
3265  ********************************************************************/
3266
3267 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3268                                   struct spoolss_NotifyInfo *info,
3269                                   TALLOC_CTX *mem_ctx)
3270 {
3271         int snum;
3272         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3273         int i;
3274         uint32_t id;
3275         struct spoolss_NotifyOption *option;
3276         struct spoolss_NotifyOptionType option_type;
3277         int count,j;
3278         print_queue_struct *queue=NULL;
3279         print_status_struct status;
3280
3281         DEBUG(4,("printer_notify_info\n"));
3282
3283         if (!Printer)
3284                 return WERR_BADFID;
3285
3286         option = Printer->notify.option;
3287         id = 0x0;
3288
3289         info->version   = 2;
3290         info->notifies  = NULL;
3291         info->count     = 0;
3292
3293         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3294            sending a ffpcn() request first */
3295
3296         if ( !option )
3297                 return WERR_BADFID;
3298
3299         get_printer_snum(p, hnd, &snum, NULL);
3300
3301         for (i=0; i<option->count; i++) {
3302                 option_type = option->types[i];
3303
3304                 switch (option_type.type) {
3305                 case PRINTER_NOTIFY_TYPE:
3306                         if(construct_notify_printer_info(Printer, info, snum,
3307                                                          &option_type, id,
3308                                                          mem_ctx))
3309                                 id--;
3310                         break;
3311
3312                 case JOB_NOTIFY_TYPE: {
3313                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3314
3315                         count = print_queue_status(snum, &queue, &status);
3316
3317                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3318                                 goto done;
3319
3320                         for (j=0; j<count; j++) {
3321                                 construct_notify_jobs_info(&queue[j], info,
3322                                                            printer, snum,
3323                                                            &option_type,
3324                                                            queue[j].job,
3325                                                            mem_ctx);
3326                         }
3327
3328                         free_a_printer(&printer, 2);
3329
3330                 done:
3331                         SAFE_FREE(queue);
3332                         break;
3333                 }
3334                 }
3335         }
3336
3337         /*
3338          * Debugging information, don't delete.
3339          */
3340         /*
3341         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3342         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3343         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3344
3345         for (i=0; i<info->count; i++) {
3346                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3347                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3348                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3349         }
3350         */
3351         return WERR_OK;
3352 }
3353
3354 /****************************************************************
3355  _spoolss_RouterRefreshPrinterChangeNotify
3356 ****************************************************************/
3357
3358 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3359                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3360 {
3361         struct spoolss_NotifyInfo *info;
3362
3363         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3364         WERROR result = WERR_BADFID;
3365
3366         /* we always have a spoolss_NotifyInfo struct */
3367         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3368         if (!info) {
3369                 result = WERR_NOMEM;
3370                 goto done;
3371         }
3372
3373         *r->out.info = info;
3374
3375         if (!Printer) {
3376                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3377                         "Invalid handle (%s:%u:%u).\n",
3378                         OUR_HANDLE(r->in.handle)));
3379                 goto done;
3380         }
3381
3382         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3383
3384         /*
3385          *      We are now using the change value, and
3386          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3387          *      I don't have a global notification system, I'm sending back all the
3388          *      informations even when _NOTHING_ has changed.
3389          */
3390
3391         /* We need to keep track of the change value to send back in
3392            RRPCN replies otherwise our updates are ignored. */
3393
3394         Printer->notify.fnpcn = true;
3395
3396         if (Printer->notify.client_connected) {
3397                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3398                         "Saving change value in request [%x]\n",
3399                         r->in.change_low));
3400                 Printer->notify.change = r->in.change_low;
3401         }
3402
3403         /* just ignore the spoolss_NotifyOption */
3404
3405         switch (Printer->printer_type) {
3406                 case SPLHND_SERVER:
3407                         result = printserver_notify_info(p, r->in.handle,
3408                                                          info, p->mem_ctx);
3409                         break;
3410
3411                 case SPLHND_PRINTER:
3412                         result = printer_notify_info(p, r->in.handle,
3413                                                      info, p->mem_ctx);
3414                         break;
3415         }
3416
3417         Printer->notify.fnpcn = false;
3418
3419 done:
3420         return result;
3421 }
3422
3423 /********************************************************************
3424  * construct_printer_info_0
3425  * fill a printer_info_0 struct
3426  ********************************************************************/
3427
3428 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3429                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3430                                       struct spoolss_PrinterInfo0 *r,
3431                                       int snum)
3432 {
3433         int count;
3434         counter_printer_0 *session_counter;
3435         time_t setuptime;
3436         print_status_struct status;
3437
3438         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3439         W_ERROR_HAVE_NO_MEMORY(r->printername);
3440
3441         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3442         W_ERROR_HAVE_NO_MEMORY(r->servername);
3443
3444         count = print_queue_length(snum, &status);
3445
3446         /* check if we already have a counter for this printer */
3447         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3448                 if (session_counter->snum == snum)
3449                         break;
3450         }
3451
3452         /* it's the first time, add it to the list */
3453         if (session_counter == NULL) {
3454                 session_counter = SMB_MALLOC_P(counter_printer_0);
3455                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3456                 ZERO_STRUCTP(session_counter);
3457                 session_counter->snum           = snum;
3458                 session_counter->counter        = 0;
3459                 DLIST_ADD(counter_list, session_counter);
3460         }
3461
3462         /* increment it */
3463         session_counter->counter++;
3464
3465         r->cjobs                        = count;
3466         r->total_jobs                   = 0;
3467         r->total_bytes                  = 0;
3468
3469         setuptime = (time_t)ntprinter->info_2->setuptime;
3470
3471         init_systemtime(&r->time, gmtime(&setuptime));
3472
3473         /* JFM:
3474          * the global_counter should be stored in a TDB as it's common to all the clients
3475          * and should be zeroed on samba startup
3476          */
3477         r->global_counter               = session_counter->counter;
3478         r->total_pages                  = 0;
3479         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3480         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3481         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3482         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3483         r->spooling                     = 0;
3484         r->max_spooling                 = 0;
3485         r->session_counter              = session_counter->counter;
3486         r->num_error_out_of_paper       = 0x0;
3487         r->num_error_not_ready          = 0x0;          /* number of print failure */
3488         r->job_error                    = 0x0;
3489         r->number_of_processors         = 0x1;
3490         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3491         r->high_part_total_bytes        = 0x0;
3492         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3493         r->last_error                   = WERR_OK;
3494         r->status                       = nt_printq_status(status.status);
3495         r->enumerate_network_printers   = 0x0;
3496         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3497         r->processor_architecture       = 0x0;
3498         r->processor_level              = 0x6;          /* 6  ???*/
3499         r->ref_ic                       = 0;
3500         r->reserved2                    = 0;
3501         r->reserved3                    = 0;
3502
3503         return WERR_OK;
3504 }
3505
3506
3507 /****************************************************************************
3508  Create a spoolss_DeviceMode struct. Returns talloced memory.
3509 ****************************************************************************/
3510
3511 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3512                                               const char *servicename)
3513 {
3514         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3515         struct spoolss_DeviceMode *devmode = NULL;
3516
3517         DEBUG(7,("construct_dev_mode\n"));
3518
3519         DEBUGADD(8,("getting printer characteristics\n"));
3520
3521         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3522                 return NULL;
3523
3524         if (!printer->info_2->devmode) {
3525                 DEBUG(5, ("BONG! There was no device mode!\n"));
3526                 goto done;
3527         }
3528
3529         devmode = talloc_steal(mem_ctx, printer->info_2->devmode);
3530
3531 done:
3532         free_a_printer(&printer,2);
3533
3534         return devmode;
3535 }
3536
3537 /********************************************************************
3538  * construct_printer_info1
3539  * fill a spoolss_PrinterInfo1 struct
3540 ********************************************************************/
3541
3542 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3543                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3544                                       uint32_t flags,
3545                                       struct spoolss_PrinterInfo1 *r,
3546                                       int snum)
3547 {
3548         r->flags                = flags;
3549
3550         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3551                                                   ntprinter->info_2->printername,
3552                                                   ntprinter->info_2->drivername,
3553                                                   ntprinter->info_2->location);
3554         W_ERROR_HAVE_NO_MEMORY(r->description);
3555
3556         if (*ntprinter->info_2->comment == '\0') {
3557                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3558         } else {
3559                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3560         }
3561         W_ERROR_HAVE_NO_MEMORY(r->comment);
3562
3563         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3564         W_ERROR_HAVE_NO_MEMORY(r->name);
3565
3566         return WERR_OK;
3567 }
3568
3569 /********************************************************************
3570  * construct_printer_info2
3571  * fill a spoolss_PrinterInfo2 struct
3572 ********************************************************************/
3573
3574 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3575                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3576                                       struct spoolss_PrinterInfo2 *r,
3577                                       int snum)
3578 {
3579         int count;
3580
3581         print_status_struct status;
3582
3583         count = print_queue_length(snum, &status);
3584
3585         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3586         W_ERROR_HAVE_NO_MEMORY(r->servername);
3587         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3588         W_ERROR_HAVE_NO_MEMORY(r->printername);
3589         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3590         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3591         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3592         W_ERROR_HAVE_NO_MEMORY(r->portname);
3593         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3594         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3595
3596         if (*ntprinter->info_2->comment == '\0') {
3597                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3598         } else {
3599                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3600         }
3601         W_ERROR_HAVE_NO_MEMORY(r->comment);
3602
3603         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3604         W_ERROR_HAVE_NO_MEMORY(r->location);
3605         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3606         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3607         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3608         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3609         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3610         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3611         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3612         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3613
3614         r->attributes           = ntprinter->info_2->attributes;
3615
3616         r->priority             = ntprinter->info_2->priority;
3617         r->defaultpriority      = ntprinter->info_2->default_priority;
3618         r->starttime            = ntprinter->info_2->starttime;
3619         r->untiltime            = ntprinter->info_2->untiltime;
3620         r->status               = nt_printq_status(status.status);
3621         r->cjobs                = count;
3622         r->averageppm           = ntprinter->info_2->averageppm;
3623
3624         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3625         if (!r->devmode) {
3626                 DEBUG(8,("Returning NULL Devicemode!\n"));
3627         }
3628
3629         r->secdesc              = NULL;
3630
3631         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3632                 /* don't use talloc_steal() here unless you do a deep steal of all
3633                    the SEC_DESC members */
3634
3635                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3636         }
3637
3638         return WERR_OK;
3639 }
3640
3641 /********************************************************************
3642  * construct_printer_info3
3643  * fill a spoolss_PrinterInfo3 struct
3644  ********************************************************************/
3645
3646 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3647                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3648                                       struct spoolss_PrinterInfo3 *r,
3649                                       int snum)
3650 {
3651         /* These are the components of the SD we are returning. */
3652
3653         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3654                 /* don't use talloc_steal() here unless you do a deep steal of all
3655                    the SEC_DESC members */
3656
3657                 r->secdesc = dup_sec_desc(mem_ctx,
3658                                           ntprinter->info_2->secdesc_buf->sd);
3659                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3660         }
3661
3662         return WERR_OK;
3663 }
3664
3665 /********************************************************************
3666  * construct_printer_info4
3667  * fill a spoolss_PrinterInfo4 struct
3668  ********************************************************************/
3669
3670 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3671                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3672                                       struct spoolss_PrinterInfo4 *r,
3673                                       int snum)
3674 {
3675         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3676         W_ERROR_HAVE_NO_MEMORY(r->printername);
3677         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3678         W_ERROR_HAVE_NO_MEMORY(r->servername);
3679
3680         r->attributes   = ntprinter->info_2->attributes;
3681
3682         return WERR_OK;
3683 }
3684
3685 /********************************************************************
3686  * construct_printer_info5
3687  * fill a spoolss_PrinterInfo5 struct
3688  ********************************************************************/
3689
3690 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3691                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3692                                       struct spoolss_PrinterInfo5 *r,
3693                                       int snum)
3694 {
3695         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3696         W_ERROR_HAVE_NO_MEMORY(r->printername);
3697         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3698         W_ERROR_HAVE_NO_MEMORY(r->portname);
3699
3700         r->attributes   = ntprinter->info_2->attributes;
3701
3702         /* these two are not used by NT+ according to MSDN */
3703
3704         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3705         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3706
3707         return WERR_OK;
3708 }
3709
3710 /********************************************************************
3711  * construct_printer_info_6
3712  * fill a spoolss_PrinterInfo6 struct
3713  ********************************************************************/
3714
3715 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3716                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3717                                       struct spoolss_PrinterInfo6 *r,
3718                                       int snum)
3719 {
3720         int count;
3721         print_status_struct status;
3722
3723         count = print_queue_length(snum, &status);
3724
3725         r->status = nt_printq_status(status.status);
3726
3727         return WERR_OK;
3728 }
3729
3730 /********************************************************************
3731  * construct_printer_info7
3732  * fill a spoolss_PrinterInfo7 struct
3733  ********************************************************************/
3734
3735 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3736                                       Printer_entry *print_hnd,
3737                                       struct spoolss_PrinterInfo7 *r,
3738                                       int snum)
3739 {
3740         struct GUID guid;
3741
3742         if (is_printer_published(print_hnd, snum, &guid)) {
3743                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3744                 r->action = DSPRINT_PUBLISH;
3745         } else {
3746                 r->guid = talloc_strdup(mem_ctx, "");
3747                 r->action = DSPRINT_UNPUBLISH;
3748         }
3749         W_ERROR_HAVE_NO_MEMORY(r->guid);
3750
3751         return WERR_OK;
3752 }
3753
3754 /********************************************************************
3755  * construct_printer_info8
3756  * fill a spoolss_PrinterInfo8 struct
3757  ********************************************************************/
3758
3759 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3760                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3761                                       struct spoolss_DeviceModeInfo *r,
3762                                       int snum)
3763 {
3764         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3765         if (!r->devmode) {
3766                 DEBUG(8,("Returning NULL Devicemode!\n"));
3767         }
3768
3769         return WERR_OK;
3770 }
3771
3772
3773 /********************************************************************
3774 ********************************************************************/
3775
3776 static bool snum_is_shared_printer(int snum)
3777 {
3778         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3779 }
3780
3781 /********************************************************************
3782  Spoolss_enumprinters.
3783 ********************************************************************/
3784
3785 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3786                                            uint32_t level,
3787                                            uint32_t flags,
3788                                            union spoolss_PrinterInfo **info_p,
3789                                            uint32_t *count_p)
3790 {
3791         int snum;
3792         int n_services = lp_numservices();
3793         union spoolss_PrinterInfo *info = NULL;
3794         uint32_t count = 0;
3795         WERROR result = WERR_OK;
3796
3797         *count_p = 0;
3798         *info_p = NULL;
3799
3800         for (snum = 0; snum < n_services; snum++) {
3801
3802                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3803
3804                 if (!snum_is_shared_printer(snum)) {
3805                         continue;
3806                 }
3807
3808                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3809                         lp_servicename(snum), snum));
3810
3811                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3812                                             union spoolss_PrinterInfo,
3813                                             count + 1);
3814                 if (!info) {
3815                         result = WERR_NOMEM;
3816                         goto out;
3817                 }
3818
3819                 result = get_a_printer(NULL, &ntprinter, 2,
3820                                        lp_const_servicename(snum));
3821                 if (!W_ERROR_IS_OK(result)) {
3822                         goto out;
3823                 }
3824
3825                 switch (level) {
3826                 case 0:
3827                         result = construct_printer_info0(info, ntprinter,
3828                                                          &info[count].info0, snum);
3829                         break;
3830                 case 1:
3831                         result = construct_printer_info1(info, ntprinter, flags,
3832                                                          &info[count].info1, snum);
3833                         break;
3834                 case 2:
3835                         result = construct_printer_info2(info, ntprinter,
3836                                                          &info[count].info2, snum);
3837                         break;
3838                 case 4:
3839                         result = construct_printer_info4(info, ntprinter,
3840                                                          &info[count].info4, snum);
3841                         break;
3842                 case 5:
3843                         result = construct_printer_info5(info, ntprinter,
3844                                                          &info[count].info5, snum);
3845                         break;
3846
3847                 default:
3848                         result = WERR_UNKNOWN_LEVEL;
3849                         free_a_printer(&ntprinter, 2);
3850                         goto out;
3851                 }
3852
3853                 free_a_printer(&ntprinter, 2);
3854                 if (!W_ERROR_IS_OK(result)) {
3855                         goto out;
3856                 }
3857
3858                 count++;
3859         }
3860
3861         *count_p = count;
3862         *info_p = info;
3863
3864  out:
3865         if (!W_ERROR_IS_OK(result)) {
3866                 TALLOC_FREE(info);
3867                 return result;
3868         }
3869
3870         *info_p = info;
3871
3872         return WERR_OK;
3873 }
3874
3875 /********************************************************************
3876  * handle enumeration of printers at level 0
3877  ********************************************************************/
3878
3879 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3880                                   uint32_t flags,
3881                                   const char *servername,
3882                                   union spoolss_PrinterInfo **info,
3883                                   uint32_t *count)
3884 {
3885         DEBUG(4,("enum_all_printers_info_0\n"));
3886
3887         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
3888 }
3889
3890
3891 /********************************************************************
3892 ********************************************************************/
3893
3894 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3895                                        uint32_t flags,
3896                                        union spoolss_PrinterInfo **info,
3897                                        uint32_t *count)
3898 {
3899         DEBUG(4,("enum_all_printers_info_1\n"));
3900
3901         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
3902 }
3903
3904 /********************************************************************
3905  enum_all_printers_info_1_local.
3906 *********************************************************************/
3907
3908 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3909                                              union spoolss_PrinterInfo **info,
3910                                              uint32_t *count)
3911 {
3912         DEBUG(4,("enum_all_printers_info_1_local\n"));
3913
3914         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
3915 }
3916
3917 /********************************************************************
3918  enum_all_printers_info_1_name.
3919 *********************************************************************/
3920
3921 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3922                                             const char *name,
3923                                             union spoolss_PrinterInfo **info,
3924                                             uint32_t *count)
3925 {
3926         const char *s = name;
3927
3928         DEBUG(4,("enum_all_printers_info_1_name\n"));
3929
3930         if ((name[0] == '\\') && (name[1] == '\\')) {
3931                 s = name + 2;
3932         }
3933
3934         if (!is_myname_or_ipaddr(s)) {
3935                 return WERR_INVALID_NAME;
3936         }
3937
3938         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
3939 }
3940
3941 /********************************************************************
3942  enum_all_printers_info_1_network.
3943 *********************************************************************/
3944
3945 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3946                                                const char *name,
3947                                                union spoolss_PrinterInfo **info,
3948                                                uint32_t *count)
3949 {
3950         const char *s = name;
3951
3952         DEBUG(4,("enum_all_printers_info_1_network\n"));
3953
3954         /* If we respond to a enum_printers level 1 on our name with flags
3955            set to PRINTER_ENUM_REMOTE with a list of printers then these
3956            printers incorrectly appear in the APW browse list.
3957            Specifically the printers for the server appear at the workgroup
3958            level where all the other servers in the domain are
3959            listed. Windows responds to this call with a
3960            WERR_CAN_NOT_COMPLETE so we should do the same. */
3961
3962         if (name[0] == '\\' && name[1] == '\\') {
3963                  s = name + 2;
3964         }
3965
3966         if (is_myname_or_ipaddr(s)) {
3967                  return WERR_CAN_NOT_COMPLETE;
3968         }
3969
3970         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
3971 }
3972
3973 /********************************************************************
3974  * api_spoolss_enumprinters
3975  *
3976  * called from api_spoolss_enumprinters (see this to understand)
3977  ********************************************************************/
3978
3979 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3980                                        union spoolss_PrinterInfo **info,
3981                                        uint32_t *count)
3982 {
3983         DEBUG(4,("enum_all_printers_info_2\n"));
3984
3985         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
3986 }
3987
3988 /********************************************************************
3989  * handle enumeration of printers at level 1
3990  ********************************************************************/
3991
3992 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3993                                   uint32_t flags,
3994                                   const char *name,
3995                                   union spoolss_PrinterInfo **info,
3996                                   uint32_t *count)
3997 {
3998         /* Not all the flags are equals */
3999
4000         if (flags & PRINTER_ENUM_LOCAL) {
4001                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4002         }
4003
4004         if (flags & PRINTER_ENUM_NAME) {
4005                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4006         }
4007
4008         if (flags & PRINTER_ENUM_NETWORK) {
4009                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4010         }
4011
4012         return WERR_OK; /* NT4sp5 does that */
4013 }
4014
4015 /********************************************************************
4016  * handle enumeration of printers at level 2
4017  ********************************************************************/
4018
4019 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4020                                   uint32_t flags,
4021                                   const char *servername,
4022                                   union spoolss_PrinterInfo **info,
4023                                   uint32_t *count)
4024 {
4025         if (flags & PRINTER_ENUM_LOCAL) {
4026                 return enum_all_printers_info_2(mem_ctx, info, count);
4027         }
4028
4029         if (flags & PRINTER_ENUM_NAME) {
4030                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4031                         return WERR_INVALID_NAME;
4032                 }
4033
4034                 return enum_all_printers_info_2(mem_ctx, info, count);
4035         }
4036
4037         if (flags & PRINTER_ENUM_REMOTE) {
4038                 return WERR_UNKNOWN_LEVEL;
4039         }
4040
4041         return WERR_OK;
4042 }
4043
4044 /********************************************************************
4045  * handle enumeration of printers at level 4
4046  ********************************************************************/
4047
4048 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4049                                   uint32_t flags,
4050                                   const char *servername,
4051                                   union spoolss_PrinterInfo **info,
4052                                   uint32_t *count)
4053 {
4054         DEBUG(4,("enum_all_printers_info_4\n"));
4055
4056         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4057 }
4058
4059
4060 /********************************************************************
4061  * handle enumeration of printers at level 5
4062  ********************************************************************/
4063
4064 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4065                                   uint32_t flags,
4066                                   const char *servername,
4067                                   union spoolss_PrinterInfo **info,
4068                                   uint32_t *count)
4069 {
4070         DEBUG(4,("enum_all_printers_info_5\n"));
4071
4072         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4073 }
4074
4075 /****************************************************************
4076  _spoolss_EnumPrinters
4077 ****************************************************************/
4078
4079 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4080                              struct spoolss_EnumPrinters *r)
4081 {
4082         const char *name = NULL;
4083         WERROR result;
4084
4085         /* that's an [in out] buffer */
4086
4087         if (!r->in.buffer && (r->in.offered != 0)) {
4088                 return WERR_INVALID_PARAM;
4089         }
4090
4091         DEBUG(4,("_spoolss_EnumPrinters\n"));
4092
4093         *r->out.needed = 0;
4094         *r->out.count = 0;
4095         *r->out.info = NULL;
4096
4097         /*
4098          * Level 1:
4099          *          flags==PRINTER_ENUM_NAME
4100          *           if name=="" then enumerates all printers
4101          *           if name!="" then enumerate the printer
4102          *          flags==PRINTER_ENUM_REMOTE
4103          *          name is NULL, enumerate printers
4104          * Level 2: name!="" enumerates printers, name can't be NULL
4105          * Level 3: doesn't exist
4106          * Level 4: does a local registry lookup
4107          * Level 5: same as Level 2
4108          */
4109
4110         if (r->in.server) {
4111                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4112                 W_ERROR_HAVE_NO_MEMORY(name);
4113         }
4114
4115         switch (r->in.level) {
4116         case 0:
4117                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4118                                              r->out.info, r->out.count);
4119                 break;
4120         case 1:
4121                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4122                                              r->out.info, r->out.count);
4123                 break;
4124         case 2:
4125                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4126                                              r->out.info, r->out.count);
4127                 break;
4128         case 4:
4129                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4130                                              r->out.info, r->out.count);
4131                 break;
4132         case 5:
4133                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4134                                              r->out.info, r->out.count);
4135                 break;
4136         default:
4137                 return WERR_UNKNOWN_LEVEL;
4138         }
4139
4140         if (!W_ERROR_IS_OK(result)) {
4141                 return result;
4142         }
4143
4144         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4145                                                      spoolss_EnumPrinters, 
4146                                                      *r->out.info, r->in.level,
4147                                                      *r->out.count);
4148         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4149         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4150
4151         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4152 }
4153
4154 /****************************************************************
4155  _spoolss_GetPrinter
4156 ****************************************************************/
4157
4158 WERROR _spoolss_GetPrinter(pipes_struct *p,
4159                            struct spoolss_GetPrinter *r)
4160 {
4161         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4162         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4163         WERROR result = WERR_OK;
4164
4165         int snum;
4166
4167         /* that's an [in out] buffer */
4168
4169         if (!r->in.buffer && (r->in.offered != 0)) {
4170                 return WERR_INVALID_PARAM;
4171         }
4172
4173         *r->out.needed = 0;
4174
4175         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4176                 return WERR_BADFID;
4177         }
4178
4179         result = get_a_printer(Printer, &ntprinter, 2,
4180                                lp_const_servicename(snum));
4181         if (!W_ERROR_IS_OK(result)) {
4182                 return result;
4183         }
4184
4185         switch (r->in.level) {
4186         case 0:
4187                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4188                                                  &r->out.info->info0, snum);
4189                 break;
4190         case 1:
4191                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4192                                                  PRINTER_ENUM_ICON8,
4193                                                  &r->out.info->info1, snum);
4194                 break;
4195         case 2:
4196                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4197                                                  &r->out.info->info2, snum);
4198                 break;
4199         case 3:
4200                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4201                                                  &r->out.info->info3, snum);
4202                 break;
4203         case 4:
4204                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4205                                                  &r->out.info->info4, snum);
4206                 break;
4207         case 5:
4208                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4209                                                  &r->out.info->info5, snum);
4210                 break;
4211         case 6:
4212                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4213                                                  &r->out.info->info6, snum);
4214                 break;
4215         case 7:
4216                 result = construct_printer_info7(p->mem_ctx, Printer,
4217                                                  &r->out.info->info7, snum);
4218                 break;
4219         case 8:
4220                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4221                                                  &r->out.info->info8, snum);
4222                 break;
4223         default:
4224                 result = WERR_UNKNOWN_LEVEL;
4225                 break;
4226         }
4227
4228         free_a_printer(&ntprinter, 2);
4229
4230         if (!W_ERROR_IS_OK(result)) {
4231                 TALLOC_FREE(r->out.info);
4232                 return result;
4233         }
4234
4235         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4236                                                r->out.info, r->in.level);
4237         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4238
4239         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4240 }
4241
4242 /********************************************************************
4243  ********************************************************************/
4244
4245 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4246                                                   const char **string_array,
4247                                                   const char *cservername)
4248 {
4249         int i, num_strings = 0;
4250         const char **array = NULL;
4251
4252         if (!string_array) {
4253                 return NULL;
4254         }
4255
4256         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4257
4258                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4259                                                   cservername, string_array[i]);
4260                 if (!str) {
4261                         TALLOC_FREE(array);
4262                         return NULL;
4263                 }
4264
4265
4266                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4267                         TALLOC_FREE(array);
4268                         return NULL;
4269                 }
4270         }
4271
4272         if (i > 0) {
4273                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4274                              &array, &num_strings);
4275         }
4276
4277         return array;
4278 }
4279
4280 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4281         do { \
4282                 if (in && strlen(in)) { \
4283                         out = talloc_strdup(mem_ctx, in); \
4284                         W_ERROR_HAVE_NO_MEMORY(out); \
4285                 } else { \
4286                         out = NULL; \
4287                 } \
4288         } while (0);
4289
4290 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4291         do { \
4292                 if (in && strlen(in)) { \
4293                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4294                 } else { \
4295                         out = talloc_strdup(mem_ctx, ""); \
4296                 } \
4297                 W_ERROR_HAVE_NO_MEMORY(out); \
4298         } while (0);
4299
4300 /********************************************************************
4301  * fill a spoolss_DriverInfo1 struct
4302  ********************************************************************/
4303
4304 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4305                                         struct spoolss_DriverInfo1 *r,
4306                                         const struct spoolss_DriverInfo8 *driver,
4307                                         const char *servername)
4308 {
4309         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4310         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4311
4312         return WERR_OK;
4313 }
4314
4315 /********************************************************************
4316  * fill a spoolss_DriverInfo2 struct
4317  ********************************************************************/
4318
4319 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4320                                         struct spoolss_DriverInfo2 *r,
4321                                         const struct spoolss_DriverInfo8 *driver,
4322                                         const char *servername)
4323
4324 {
4325         const char *cservername = canon_servername(servername);
4326
4327         r->version              = driver->version;
4328
4329         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4330         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4331         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4332         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4333
4334         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4335                                driver->driver_path,
4336                                r->driver_path);
4337
4338         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4339                                driver->data_file,
4340                                r->data_file);
4341
4342         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4343                                driver->config_file,
4344                                r->config_file);
4345
4346         return WERR_OK;
4347 }
4348
4349 /********************************************************************
4350  * fill a spoolss_DriverInfo3 struct
4351  ********************************************************************/
4352
4353 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4354                                         struct spoolss_DriverInfo3 *r,
4355                                         const struct spoolss_DriverInfo8 *driver,
4356                                         const char *servername)
4357 {
4358         const char *cservername = canon_servername(servername);
4359
4360         r->version              = driver->version;
4361
4362         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4363         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4364         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4365         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4366
4367         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4368                                driver->driver_path,
4369                                r->driver_path);
4370
4371         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4372                                driver->data_file,
4373                                r->data_file);
4374
4375         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4376                                driver->config_file,
4377                                r->config_file);
4378
4379         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4380                                driver->help_file,
4381                                r->help_file);
4382
4383         FILL_DRIVER_STRING(mem_ctx,
4384                            driver->monitor_name,
4385                            r->monitor_name);
4386
4387         FILL_DRIVER_STRING(mem_ctx,
4388                            driver->default_datatype,
4389                            r->default_datatype);
4390
4391         r->dependent_files = string_array_from_driver_info(mem_ctx,
4392                                                            driver->dependent_files,
4393                                                            cservername);
4394         return WERR_OK;
4395 }
4396
4397 /********************************************************************
4398  * fill a spoolss_DriverInfo4 struct
4399  ********************************************************************/
4400
4401 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4402                                         struct spoolss_DriverInfo4 *r,
4403                                         const struct spoolss_DriverInfo8 *driver,
4404                                         const char *servername)
4405 {
4406         const char *cservername = canon_servername(servername);
4407
4408         r->version              = driver->version;
4409
4410         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4411         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4412         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4413         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4414
4415         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4416                                driver->driver_path,
4417                                r->driver_path);
4418
4419         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4420                                driver->data_file,
4421                                r->data_file);
4422
4423         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4424                                driver->config_file,
4425                                r->config_file);
4426
4427         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4428                                driver->help_file,
4429                                r->help_file);
4430
4431         r->dependent_files = string_array_from_driver_info(mem_ctx,
4432                                                            driver->dependent_files,
4433                                                            cservername);
4434
4435         FILL_DRIVER_STRING(mem_ctx,
4436                            driver->monitor_name,
4437                            r->monitor_name);
4438
4439         FILL_DRIVER_STRING(mem_ctx,
4440                            driver->default_datatype,
4441                            r->default_datatype);
4442
4443         r->previous_names = string_array_from_driver_info(mem_ctx,
4444                                                           driver->previous_names,
4445                                                           cservername);
4446
4447         return WERR_OK;
4448 }
4449
4450 /********************************************************************
4451  * fill a spoolss_DriverInfo5 struct
4452  ********************************************************************/
4453
4454 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4455                                         struct spoolss_DriverInfo5 *r,
4456                                         const struct spoolss_DriverInfo8 *driver,
4457                                         const char *servername)
4458 {
4459         const char *cservername = canon_servername(servername);
4460
4461         r->version              = driver->version;
4462
4463         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4464         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4465         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4466         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4467
4468         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4469                                driver->driver_path,
4470                                r->driver_path);
4471
4472         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4473                                driver->data_file,
4474                                r->data_file);
4475
4476         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4477                                driver->config_file,
4478                                r->config_file);
4479
4480         r->driver_attributes    = 0;
4481         r->config_version       = 0;
4482         r->driver_version       = 0;
4483
4484         return WERR_OK;
4485 }
4486 /********************************************************************
4487  * fill a spoolss_DriverInfo6 struct
4488  ********************************************************************/
4489
4490 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4491                                         struct spoolss_DriverInfo6 *r,
4492                                         const struct spoolss_DriverInfo8 *driver,
4493                                         const char *servername)
4494 {
4495         const char *cservername = canon_servername(servername);
4496
4497         r->version              = driver->version;
4498
4499         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4500         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4501         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4502         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4503
4504         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4505                                driver->driver_path,
4506                                r->driver_path);
4507
4508         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4509                                driver->data_file,
4510                                r->data_file);
4511
4512         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4513                                driver->config_file,
4514                                r->config_file);
4515
4516         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4517                                driver->help_file,
4518                                r->help_file);
4519
4520         FILL_DRIVER_STRING(mem_ctx,
4521                            driver->monitor_name,
4522                            r->monitor_name);
4523
4524         FILL_DRIVER_STRING(mem_ctx,
4525                            driver->default_datatype,
4526                            r->default_datatype);
4527
4528         r->dependent_files = string_array_from_driver_info(mem_ctx,
4529                                                            driver->dependent_files,
4530                                                            cservername);
4531         r->previous_names = string_array_from_driver_info(mem_ctx,
4532                                                           driver->previous_names,
4533                                                           cservername);
4534
4535         r->driver_date          = driver->driver_date;
4536         r->driver_version       = driver->driver_version;
4537
4538         FILL_DRIVER_STRING(mem_ctx,
4539                            driver->manufacturer_name,
4540                            r->manufacturer_name);
4541         FILL_DRIVER_STRING(mem_ctx,
4542                            driver->manufacturer_url,
4543                            r->manufacturer_url);
4544         FILL_DRIVER_STRING(mem_ctx,
4545                            driver->hardware_id,
4546                            r->hardware_id);
4547         FILL_DRIVER_STRING(mem_ctx,
4548                            driver->provider,
4549                            r->provider);
4550
4551         return WERR_OK;
4552 }
4553
4554 /********************************************************************
4555  * fill a spoolss_DriverInfo8 struct
4556  ********************************************************************/
4557
4558 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4559                                         struct spoolss_DriverInfo8 *r,
4560                                         const struct spoolss_DriverInfo8 *driver,
4561                                         const char *servername)
4562 {
4563         const char *cservername = canon_servername(servername);
4564
4565         r->version              = driver->version;
4566
4567         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4568         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4569         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4570         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4571
4572         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573                                driver->driver_path,
4574                                r->driver_path);
4575
4576         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4577                                driver->data_file,
4578                                r->data_file);
4579
4580         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4581                                driver->config_file,
4582                                r->config_file);
4583
4584         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4585                                driver->help_file,
4586                                r->help_file);
4587
4588         FILL_DRIVER_STRING(mem_ctx,
4589                            driver->monitor_name,
4590                            r->monitor_name);
4591
4592         FILL_DRIVER_STRING(mem_ctx,
4593                            driver->default_datatype,
4594                            r->default_datatype);
4595
4596         r->dependent_files = string_array_from_driver_info(mem_ctx,
4597                                                            driver->dependent_files,
4598                                                            cservername);
4599         r->previous_names = string_array_from_driver_info(mem_ctx,
4600                                                           driver->previous_names,
4601                                                           cservername);
4602
4603         r->driver_date          = driver->driver_date;
4604         r->driver_version       = driver->driver_version;
4605
4606         FILL_DRIVER_STRING(mem_ctx,
4607                            driver->manufacturer_name,
4608                            r->manufacturer_name);
4609         FILL_DRIVER_STRING(mem_ctx,
4610                            driver->manufacturer_url,
4611                            r->manufacturer_url);
4612         FILL_DRIVER_STRING(mem_ctx,
4613                            driver->hardware_id,
4614                            r->hardware_id);
4615         FILL_DRIVER_STRING(mem_ctx,
4616                            driver->provider,
4617                            r->provider);
4618
4619         FILL_DRIVER_STRING(mem_ctx,
4620                            driver->print_processor,
4621                            r->print_processor);
4622         FILL_DRIVER_STRING(mem_ctx,
4623                            driver->vendor_setup,
4624                            r->vendor_setup);
4625
4626         r->color_profiles = string_array_from_driver_info(mem_ctx,
4627                                                           driver->color_profiles,
4628                                                           cservername);
4629
4630         FILL_DRIVER_STRING(mem_ctx,
4631                            driver->inf_path,
4632                            r->inf_path);
4633
4634         r->printer_driver_attributes    = driver->printer_driver_attributes;
4635
4636         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4637                                                                     driver->core_driver_dependencies,
4638                                                                     cservername);
4639
4640         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4641         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4642
4643         return WERR_OK;
4644 }
4645
4646 #if 0 /* disabled until marshalling issues are resolved - gd */
4647 /********************************************************************
4648  ********************************************************************/
4649
4650 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4651                                           struct spoolss_DriverFileInfo *r,
4652                                           const char *cservername,
4653                                           const char *file_name,
4654                                           enum spoolss_DriverFileType file_type,
4655                                           uint32_t file_version)
4656 {
4657         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4658                                           cservername, file_name);
4659         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4660         r->file_type    = file_type;
4661         r->file_version = file_version;
4662
4663         return WERR_OK;
4664 }
4665
4666 /********************************************************************
4667  ********************************************************************/
4668
4669 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4670                                                  const struct spoolss_DriverInfo8 *driver,
4671                                                  const char *cservername,
4672                                                  struct spoolss_DriverFileInfo **info_p,
4673                                                  uint32_t *count_p)
4674 {
4675         struct spoolss_DriverFileInfo *info = NULL;
4676         uint32_t count = 0;
4677         WERROR result;
4678         uint32_t i;
4679
4680         *info_p = NULL;
4681         *count_p = 0;
4682
4683         if (strlen(driver->driver_path)) {
4684                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4685                                             struct spoolss_DriverFileInfo,
4686                                             count + 1);
4687                 W_ERROR_HAVE_NO_MEMORY(info);
4688                 result = fill_spoolss_DriverFileInfo(info,
4689                                                      &info[count],
4690                                                      cservername,
4691                                                      driver->driver_path,
4692                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4693                                                      0);
4694                 W_ERROR_NOT_OK_RETURN(result);
4695                 count++;
4696         }
4697
4698         if (strlen(driver->config_file)) {
4699                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4700                                             struct spoolss_DriverFileInfo,
4701                                             count + 1);
4702                 W_ERROR_HAVE_NO_MEMORY(info);
4703                 result = fill_spoolss_DriverFileInfo(info,
4704                                                      &info[count],
4705                                                      cservername,
4706                                                      driver->config_file,
4707                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4708                                                      0);
4709                 W_ERROR_NOT_OK_RETURN(result);
4710                 count++;
4711         }
4712
4713         if (strlen(driver->data_file)) {
4714                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4715                                             struct spoolss_DriverFileInfo,
4716                                             count + 1);
4717                 W_ERROR_HAVE_NO_MEMORY(info);
4718                 result = fill_spoolss_DriverFileInfo(info,
4719                                                      &info[count],
4720                                                      cservername,
4721                                                      driver->data_file,
4722                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4723                                                      0);
4724                 W_ERROR_NOT_OK_RETURN(result);
4725                 count++;
4726         }
4727
4728         if (strlen(driver->help_file)) {
4729                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4730                                             struct spoolss_DriverFileInfo,
4731                                             count + 1);
4732                 W_ERROR_HAVE_NO_MEMORY(info);
4733                 result = fill_spoolss_DriverFileInfo(info,
4734                                                      &info[count],
4735                                                      cservername,
4736                                                      driver->help_file,
4737                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4738                                                      0);
4739                 W_ERROR_NOT_OK_RETURN(result);
4740                 count++;
4741         }
4742
4743         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4744                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4745                                             struct spoolss_DriverFileInfo,
4746                                             count + 1);
4747                 W_ERROR_HAVE_NO_MEMORY(info);
4748                 result = fill_spoolss_DriverFileInfo(info,
4749                                                      &info[count],
4750                                                      cservername,
4751                                                      driver->dependent_files[i],
4752                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4753                                                      0);
4754                 W_ERROR_NOT_OK_RETURN(result);
4755                 count++;
4756         }
4757
4758         *info_p = info;
4759         *count_p = count;
4760
4761         return WERR_OK;
4762 }
4763
4764 /********************************************************************
4765  * fill a spoolss_DriverInfo101 struct
4766  ********************************************************************/
4767
4768 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4769                                           struct spoolss_DriverInfo101 *r,
4770                                           const struct spoolss_DriverInfo8 *driver,
4771                                           const char *servername)
4772 {
4773         const char *cservername = canon_servername(servername);
4774         WERROR result;
4775
4776         r->version              = driver->version;
4777
4778         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4779         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4780         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4781         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4782
4783         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4784                                                     cservername,
4785                                                     &r->file_info,
4786                                                     &r->file_count);
4787         if (!W_ERROR_IS_OK(result)) {
4788                 return result;
4789         }
4790
4791         FILL_DRIVER_STRING(mem_ctx,
4792                            driver->monitor_name,
4793                            r->monitor_name);
4794
4795         FILL_DRIVER_STRING(mem_ctx,
4796                            driver->default_datatype,
4797                            r->default_datatype);
4798
4799         r->previous_names = string_array_from_driver_info(mem_ctx,
4800                                                           driver->previous_names,
4801                                                           cservername);
4802         r->driver_date          = driver->driver_date;
4803         r->driver_version       = driver->driver_version;
4804
4805         FILL_DRIVER_STRING(mem_ctx,
4806                            driver->manufacturer_name,
4807                            r->manufacturer_name);
4808         FILL_DRIVER_STRING(mem_ctx,
4809                            driver->manufacturer_url,
4810                            r->manufacturer_url);
4811         FILL_DRIVER_STRING(mem_ctx,
4812                            driver->hardware_id,
4813                            r->hardware_id);
4814         FILL_DRIVER_STRING(mem_ctx,
4815                            driver->provider,
4816                            r->provider);
4817
4818         return WERR_OK;
4819 }
4820 #endif
4821 /********************************************************************
4822  ********************************************************************/
4823
4824 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4825                                                   uint32_t level,
4826                                                   union spoolss_DriverInfo *r,
4827                                                   int snum,
4828                                                   const char *servername,
4829                                                   const char *architecture,
4830                                                   uint32_t version)
4831 {
4832         NT_PRINTER_INFO_LEVEL *printer = NULL;
4833         struct spoolss_DriverInfo8 *driver;
4834         WERROR result;
4835
4836         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4837
4838         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4839                 win_errstr(result)));
4840
4841         if (!W_ERROR_IS_OK(result)) {
4842                 return WERR_INVALID_PRINTER_NAME;
4843         }
4844
4845         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4846                                       architecture, version);
4847
4848         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4849                 win_errstr(result)));
4850
4851         if (!W_ERROR_IS_OK(result)) {
4852                 /*
4853                  * Is this a W2k client ?
4854                  */
4855
4856                 if (version < 3) {
4857                         free_a_printer(&printer, 2);
4858                         return WERR_UNKNOWN_PRINTER_DRIVER;
4859                 }
4860
4861                 /* Yes - try again with a WinNT driver. */
4862                 version = 2;
4863                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4864                                               architecture, version);
4865                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4866                         win_errstr(result)));
4867                 if (!W_ERROR_IS_OK(result)) {
4868                         free_a_printer(&printer, 2);
4869                         return WERR_UNKNOWN_PRINTER_DRIVER;
4870                 }
4871         }
4872
4873         switch (level) {
4874         case 1:
4875                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4876                 break;
4877         case 2:
4878                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4879                 break;
4880         case 3:
4881                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4882                 break;
4883         case 4:
4884                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4885                 break;
4886         case 5:
4887                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4888                 break;
4889         case 6:
4890                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4891                 break;
4892         case 8:
4893                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4894                 break;
4895 #if 0 /* disabled until marshalling issues are resolved - gd */
4896         case 101:
4897                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4898                 break;
4899 #endif
4900         default:
4901                 result = WERR_UNKNOWN_LEVEL;
4902                 break;
4903         }
4904
4905         free_a_printer(&printer, 2);
4906         free_a_printer_driver(driver);
4907
4908         return result;
4909 }
4910
4911 /****************************************************************
4912  _spoolss_GetPrinterDriver2
4913 ****************************************************************/
4914
4915 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4916                                   struct spoolss_GetPrinterDriver2 *r)
4917 {
4918         Printer_entry *printer;
4919         WERROR result;
4920
4921         const char *servername;
4922         int snum;
4923
4924         /* that's an [in out] buffer */
4925
4926         if (!r->in.buffer && (r->in.offered != 0)) {
4927                 return WERR_INVALID_PARAM;
4928         }
4929
4930         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4931
4932         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4933                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4934                 return WERR_INVALID_PRINTER_NAME;
4935         }
4936
4937         *r->out.needed = 0;
4938         *r->out.server_major_version = 0;
4939         *r->out.server_minor_version = 0;
4940
4941         servername = get_server_name(printer);
4942
4943         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4944                 return WERR_BADFID;
4945         }
4946
4947         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
4948                                                      r->out.info, snum,
4949                                                      servername,
4950                                                      r->in.architecture,
4951                                                      r->in.client_major_version);
4952         if (!W_ERROR_IS_OK(result)) {
4953                 TALLOC_FREE(r->out.info);
4954                 return result;
4955         }
4956
4957         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
4958                                                r->out.info, r->in.level);
4959         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4960
4961         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4962 }
4963
4964
4965 /****************************************************************
4966  _spoolss_StartPagePrinter
4967 ****************************************************************/
4968
4969 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4970                                  struct spoolss_StartPagePrinter *r)
4971 {
4972         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4973
4974         if (!Printer) {
4975                 DEBUG(3,("_spoolss_StartPagePrinter: "
4976                         "Error in startpageprinter printer handle\n"));
4977                 return WERR_BADFID;
4978         }
4979
4980         Printer->page_started = true;
4981         return WERR_OK;
4982 }
4983
4984 /****************************************************************
4985  _spoolss_EndPagePrinter
4986 ****************************************************************/
4987
4988 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4989                                struct spoolss_EndPagePrinter *r)
4990 {
4991         int snum;
4992
4993         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4994
4995         if (!Printer) {
4996                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
4997                         OUR_HANDLE(r->in.handle)));
4998                 return WERR_BADFID;
4999         }
5000
5001         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5002                 return WERR_BADFID;
5003
5004         Printer->page_started = false;
5005         print_job_endpage(snum, Printer->jobid);
5006
5007         return WERR_OK;
5008 }
5009
5010 /****************************************************************
5011  _spoolss_StartDocPrinter
5012 ****************************************************************/
5013
5014 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5015                                 struct spoolss_StartDocPrinter *r)
5016 {
5017         struct spoolss_DocumentInfo1 *info_1;
5018         int snum;
5019         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5020
5021         if (!Printer) {
5022                 DEBUG(2,("_spoolss_StartDocPrinter: "
5023                         "Invalid handle (%s:%u:%u)\n",
5024                         OUR_HANDLE(r->in.handle)));
5025                 return WERR_BADFID;
5026         }
5027
5028         if (r->in.level != 1) {
5029                 return WERR_UNKNOWN_LEVEL;
5030         }
5031
5032         info_1 = r->in.info.info1;
5033
5034         /*
5035          * a nice thing with NT is it doesn't listen to what you tell it.
5036          * when asked to send _only_ RAW datas, it tries to send datas
5037          * in EMF format.
5038          *
5039          * So I add checks like in NT Server ...
5040          */
5041
5042         if (info_1->datatype) {
5043                 if (strcmp(info_1->datatype, "RAW") != 0) {
5044                         *r->out.job_id = 0;
5045                         return WERR_INVALID_DATATYPE;
5046                 }
5047         }
5048
5049         /* get the share number of the printer */
5050         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5051                 return WERR_BADFID;
5052         }
5053
5054         Printer->jobid = print_job_start(p->server_info, snum,
5055                                          info_1->document_name,
5056                                          Printer->devmode);
5057
5058         /* An error occured in print_job_start() so return an appropriate
5059            NT error code. */
5060
5061         if (Printer->jobid == -1) {
5062                 return map_werror_from_unix(errno);
5063         }
5064
5065         Printer->document_started = true;
5066         *r->out.job_id = Printer->jobid;
5067
5068         return WERR_OK;
5069 }
5070
5071 /****************************************************************
5072  _spoolss_EndDocPrinter
5073 ****************************************************************/
5074
5075 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5076                               struct spoolss_EndDocPrinter *r)
5077 {
5078         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5079         int snum;
5080
5081         if (!Printer) {
5082                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5083                         OUR_HANDLE(r->in.handle)));
5084                 return WERR_BADFID;
5085         }
5086
5087         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5088                 return WERR_BADFID;
5089         }
5090
5091         Printer->document_started = false;
5092         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5093         /* error codes unhandled so far ... */
5094
5095         return WERR_OK;
5096 }
5097
5098 /****************************************************************
5099  _spoolss_WritePrinter
5100 ****************************************************************/
5101
5102 WERROR _spoolss_WritePrinter(pipes_struct *p,
5103                              struct spoolss_WritePrinter *r)
5104 {
5105         ssize_t buffer_written;
5106         int snum;
5107         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5108
5109         if (!Printer) {
5110                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5111                         OUR_HANDLE(r->in.handle)));
5112                 *r->out.num_written = r->in._data_size;
5113                 return WERR_BADFID;
5114         }
5115
5116         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5117                 return WERR_BADFID;
5118
5119         buffer_written = print_job_write(snum, Printer->jobid,
5120                                                    (const char *)r->in.data.data,
5121                                                    (SMB_OFF_T)-1,
5122                                                    (size_t)r->in._data_size);
5123         if (buffer_written == (ssize_t)-1) {
5124                 *r->out.num_written = 0;
5125                 if (errno == ENOSPC)
5126                         return WERR_NO_SPOOL_SPACE;
5127                 else
5128                         return WERR_ACCESS_DENIED;
5129         }
5130
5131         *r->out.num_written = r->in._data_size;
5132
5133         return WERR_OK;
5134 }
5135
5136 /********************************************************************
5137  * api_spoolss_getprinter
5138  * called from the spoolss dispatcher
5139  *
5140  ********************************************************************/
5141
5142 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5143                               pipes_struct *p)
5144 {
5145         int snum;
5146         WERROR errcode = WERR_BADFUNC;
5147         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5148
5149         if (!Printer) {
5150                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5151                         OUR_HANDLE(handle)));
5152                 return WERR_BADFID;
5153         }
5154
5155         if (!get_printer_snum(p, handle, &snum, NULL))
5156                 return WERR_BADFID;
5157
5158         switch (command) {
5159         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5160                 errcode = print_queue_pause(p->server_info, snum);
5161                 break;
5162         case SPOOLSS_PRINTER_CONTROL_RESUME:
5163         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5164                 errcode = print_queue_resume(p->server_info, snum);
5165                 break;
5166         case SPOOLSS_PRINTER_CONTROL_PURGE:
5167                 errcode = print_queue_purge(p->server_info, snum);
5168                 break;
5169         default:
5170                 return WERR_UNKNOWN_LEVEL;
5171         }
5172
5173         return errcode;
5174 }
5175
5176
5177 /****************************************************************
5178  _spoolss_AbortPrinter
5179  * From MSDN: "Deletes printer's spool file if printer is configured
5180  * for spooling"
5181 ****************************************************************/
5182
5183 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5184                              struct spoolss_AbortPrinter *r)
5185 {
5186         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5187         int             snum;
5188         WERROR          errcode = WERR_OK;
5189
5190         if (!Printer) {
5191                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5192                         OUR_HANDLE(r->in.handle)));
5193                 return WERR_BADFID;
5194         }
5195
5196         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5197                 return WERR_BADFID;
5198
5199         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5200
5201         return errcode;
5202 }
5203
5204 /********************************************************************
5205  * called by spoolss_api_setprinter
5206  * when updating a printer description
5207  ********************************************************************/
5208
5209 static WERROR update_printer_sec(struct policy_handle *handle,
5210                                  pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5211 {
5212         struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5213         WERROR result;
5214         int snum;
5215
5216         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5217
5218         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5219                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5220                          OUR_HANDLE(handle)));
5221
5222                 result = WERR_BADFID;
5223                 goto done;
5224         }
5225
5226         if (!secdesc_ctr) {
5227                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5228                 result = WERR_INVALID_PARAM;
5229                 goto done;
5230         }
5231
5232         /* Check the user has permissions to change the security
5233            descriptor.  By experimentation with two NT machines, the user
5234            requires Full Access to the printer to change security
5235            information. */
5236
5237         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5238                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5239                 result = WERR_ACCESS_DENIED;
5240                 goto done;
5241         }
5242
5243         /* NT seems to like setting the security descriptor even though
5244            nothing may have actually changed. */
5245
5246         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5247                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5248                 result = WERR_BADFID;
5249                 goto done;
5250         }
5251
5252         if (DEBUGLEVEL >= 10) {
5253                 struct security_acl *the_acl;
5254                 int i;
5255
5256                 the_acl = old_secdesc_ctr->sd->dacl;
5257                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5258                            lp_printername(snum), the_acl->num_aces));
5259
5260                 for (i = 0; i < the_acl->num_aces; i++) {
5261                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5262                                            &the_acl->aces[i].trustee),
5263                                   the_acl->aces[i].access_mask));
5264                 }
5265
5266                 the_acl = secdesc_ctr->sd->dacl;
5267
5268                 if (the_acl) {
5269                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5270                                    lp_printername(snum), the_acl->num_aces));
5271
5272                         for (i = 0; i < the_acl->num_aces; i++) {
5273                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5274                                                    &the_acl->aces[i].trustee),
5275                                            the_acl->aces[i].access_mask));
5276                         }
5277                 } else {
5278                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5279                 }
5280         }
5281
5282         new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5283         if (!new_secdesc_ctr) {
5284                 result = WERR_NOMEM;
5285                 goto done;
5286         }
5287
5288         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5289                 result = WERR_OK;
5290                 goto done;
5291         }
5292
5293         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5294
5295  done:
5296
5297         return result;
5298 }
5299
5300 /********************************************************************
5301  Canonicalize printer info from a client
5302
5303  ATTN: It does not matter what we set the servername to hear
5304  since we do the necessary work in get_a_printer() to set it to
5305  the correct value based on what the client sent in the
5306  _spoolss_open_printer_ex().
5307  ********************************************************************/
5308
5309 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5310 {
5311         fstring printername;
5312         const char *p;
5313
5314         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5315                 "portname=%s drivername=%s comment=%s location=%s\n",
5316                 info->servername, info->printername, info->sharename,
5317                 info->portname, info->drivername, info->comment, info->location));
5318
5319         /* we force some elements to "correct" values */
5320         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5321         fstrcpy(info->sharename, lp_servicename(snum));
5322
5323         /* check to see if we allow printername != sharename */
5324
5325         if ( lp_force_printername(snum) ) {
5326                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5327                         global_myname(), info->sharename );
5328         } else {
5329
5330                 /* make sure printername is in \\server\printername format */
5331
5332                 fstrcpy( printername, info->printername );
5333                 p = printername;
5334                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5335                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5336                                 p++;
5337                 }
5338
5339                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5340                          global_myname(), p );
5341         }
5342
5343         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5344         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5345
5346
5347
5348         return true;
5349 }
5350
5351 /****************************************************************************
5352 ****************************************************************************/
5353
5354 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5355 {
5356         char *cmd = lp_addport_cmd();
5357         char *command = NULL;
5358         int ret;
5359         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5360         bool is_print_op = false;
5361
5362         if ( !*cmd ) {
5363                 return WERR_ACCESS_DENIED;
5364         }
5365
5366         command = talloc_asprintf(ctx,
5367                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5368         if (!command) {
5369                 return WERR_NOMEM;
5370         }
5371
5372         if ( token )
5373                 is_print_op = user_has_privileges( token, &se_printop );
5374
5375         DEBUG(10,("Running [%s]\n", command));
5376
5377         /********* BEGIN SePrintOperatorPrivilege **********/
5378
5379         if ( is_print_op )
5380                 become_root();
5381
5382         ret = smbrun(command, NULL);
5383
5384         if ( is_print_op )
5385                 unbecome_root();
5386
5387         /********* END SePrintOperatorPrivilege **********/
5388
5389         DEBUGADD(10,("returned [%d]\n", ret));
5390
5391         TALLOC_FREE(command);
5392
5393         if ( ret != 0 ) {
5394                 return WERR_ACCESS_DENIED;
5395         }
5396
5397         return WERR_OK;
5398 }
5399
5400 /****************************************************************************
5401 ****************************************************************************/
5402
5403 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5404 {
5405         char *cmd = lp_addprinter_cmd();
5406         char **qlines;
5407         char *command = NULL;
5408         int numlines;
5409         int ret;
5410         int fd;
5411         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5412         bool is_print_op = false;
5413         char *remote_machine = talloc_strdup(ctx, "%m");
5414
5415         if (!remote_machine) {
5416                 return false;
5417         }
5418         remote_machine = talloc_sub_basic(ctx,
5419                                 current_user_info.smb_name,
5420                                 current_user_info.domain,
5421                                 remote_machine);
5422         if (!remote_machine) {
5423                 return false;
5424         }
5425
5426         command = talloc_asprintf(ctx,
5427                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5428                         cmd, printer->info_2->printername, printer->info_2->sharename,
5429                         printer->info_2->portname, printer->info_2->drivername,
5430                         printer->info_2->location, printer->info_2->comment, remote_machine);
5431         if (!command) {
5432                 return false;
5433         }
5434
5435         if ( token )
5436                 is_print_op = user_has_privileges( token, &se_printop );
5437
5438         DEBUG(10,("Running [%s]\n", command));
5439
5440         /********* BEGIN SePrintOperatorPrivilege **********/
5441
5442         if ( is_print_op )
5443                 become_root();
5444
5445         if ( (ret = smbrun(command, &fd)) == 0 ) {
5446                 /* Tell everyone we updated smb.conf. */
5447                 message_send_all(smbd_messaging_context(),
5448                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5449         }
5450
5451         if ( is_print_op )
5452                 unbecome_root();
5453
5454         /********* END SePrintOperatorPrivilege **********/
5455
5456         DEBUGADD(10,("returned [%d]\n", ret));
5457
5458         TALLOC_FREE(command);
5459         TALLOC_FREE(remote_machine);
5460
5461         if ( ret != 0 ) {
5462                 if (fd != -1)
5463                         close(fd);
5464                 return false;
5465         }
5466
5467         /* reload our services immediately */
5468         become_root();
5469         reload_services(false);
5470         unbecome_root();
5471
5472         numlines = 0;
5473         /* Get lines and convert them back to dos-codepage */
5474         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5475         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5476         close(fd);
5477
5478         /* Set the portname to what the script says the portname should be. */
5479         /* but don't require anything to be return from the script exit a good error code */
5480
5481         if (numlines) {
5482                 /* Set the portname to what the script says the portname should be. */
5483                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5484                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5485         }
5486
5487         TALLOC_FREE(qlines);
5488         return true;
5489 }
5490
5491
5492 /********************************************************************
5493  * Called by spoolss_api_setprinter
5494  * when updating a printer description.
5495  ********************************************************************/
5496
5497 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5498                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5499                              struct spoolss_DeviceMode *devmode)
5500 {
5501         int snum;
5502         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5503         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5504         WERROR result;
5505         DATA_BLOB buffer;
5506         fstring asc_buffer;
5507
5508         DEBUG(8,("update_printer\n"));
5509
5510         result = WERR_OK;
5511
5512         if (!Printer) {
5513                 result = WERR_BADFID;
5514                 goto done;
5515         }
5516
5517         if (!get_printer_snum(p, handle, &snum, NULL)) {
5518                 result = WERR_BADFID;
5519                 goto done;
5520         }
5521
5522         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5523             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5524                 result = WERR_BADFID;
5525                 goto done;
5526         }
5527
5528         DEBUGADD(8,("Converting info_2 struct\n"));
5529
5530         /*
5531          * convert_printer_info converts the incoming
5532          * info from the client and overwrites the info
5533          * just read from the tdb in the pointer 'printer'.
5534          */
5535
5536         if (!convert_printer_info(info_ctr, printer)) {
5537                 result =  WERR_NOMEM;
5538                 goto done;
5539         }
5540
5541         if (devmode) {
5542                 /* we have a valid devmode
5543                    convert it and link it*/
5544
5545                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5546                 result = copy_devicemode(printer->info_2, devmode,
5547                                          &printer->info_2->devmode);
5548                 if (!W_ERROR_IS_OK(result)) {
5549                         return result;
5550                 }
5551         }
5552
5553         /* Do sanity check on the requested changes for Samba */
5554
5555         if (!check_printer_ok(printer->info_2, snum)) {
5556                 result = WERR_INVALID_PARAM;
5557                 goto done;
5558         }
5559
5560         /* FIXME!!! If the driver has changed we really should verify that
5561            it is installed before doing much else   --jerry */
5562
5563         /* Check calling user has permission to update printer description */
5564
5565         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5566                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5567                 result = WERR_ACCESS_DENIED;
5568                 goto done;
5569         }
5570
5571         /* Call addprinter hook */
5572         /* Check changes to see if this is really needed */
5573
5574         if ( *lp_addprinter_cmd()
5575                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5576                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5577                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5578                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5579         {
5580                 /* add_printer_hook() will call reload_services() */
5581
5582                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5583                                        printer) ) {
5584                         result = WERR_ACCESS_DENIED;
5585                         goto done;
5586                 }
5587         }
5588
5589         /*
5590          * When a *new* driver is bound to a printer, the drivername is used to
5591          * lookup previously saved driver initialization info, which is then
5592          * bound to the printer, simulating what happens in the Windows arch.
5593          */
5594         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5595         {
5596                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5597                         printer->info_2->drivername));
5598
5599                 notify_printer_driver(snum, printer->info_2->drivername);
5600         }
5601
5602         /*
5603          * flag which changes actually occured.  This is a small subset of
5604          * all the possible changes.  We also have to update things in the
5605          * DsSpooler key.
5606          */
5607
5608         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5609                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5610                 winreg_set_printer_dataex(p->mem_ctx,
5611                                           p->server_info,
5612                                           printer->info_2->sharename,
5613                                           SPOOL_DSSPOOLER_KEY,
5614                                           "description",
5615                                           REG_SZ,
5616                                           buffer.data,
5617                                           buffer.length);
5618
5619                 notify_printer_comment(snum, printer->info_2->comment);
5620         }
5621
5622         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5623                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5624                 winreg_set_printer_dataex(p->mem_ctx,
5625                                           p->server_info,
5626                                           printer->info_2->sharename,
5627                                           SPOOL_DSSPOOLER_KEY,
5628                                           "shareName",
5629                                           REG_SZ,
5630                                           buffer.data,
5631                                           buffer.length);
5632
5633                 notify_printer_sharename(snum, printer->info_2->sharename);
5634         }
5635
5636         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5637                 char *pname;
5638
5639                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5640                         pname++;
5641                 else
5642                         pname = printer->info_2->printername;
5643
5644
5645                 push_reg_sz(talloc_tos(), &buffer, pname);
5646                 winreg_set_printer_dataex(p->mem_ctx,
5647                                           p->server_info,
5648                                           printer->info_2->sharename,
5649                                           SPOOL_DSSPOOLER_KEY,
5650                                           "printerName",
5651                                           REG_SZ,
5652                                           buffer.data,
5653                                           buffer.length);
5654
5655                 notify_printer_printername( snum, pname );
5656         }
5657
5658         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5659                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5660                 winreg_set_printer_dataex(p->mem_ctx,
5661                                           p->server_info,
5662                                           printer->info_2->sharename,
5663                                           SPOOL_DSSPOOLER_KEY,
5664                                           "portName",
5665                                           REG_SZ,
5666                                           buffer.data,
5667                                           buffer.length);
5668
5669                 notify_printer_port(snum, printer->info_2->portname);
5670         }
5671
5672         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5673                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5674                 winreg_set_printer_dataex(p->mem_ctx,
5675                                           p->server_info,
5676                                           printer->info_2->sharename,
5677                                           SPOOL_DSSPOOLER_KEY,
5678                                           "location",
5679                                           REG_SZ,
5680                                           buffer.data,
5681                                           buffer.length);
5682
5683                 notify_printer_location(snum, printer->info_2->location);
5684         }
5685
5686         /* here we need to update some more DsSpooler keys */
5687         /* uNCName, serverName, shortServerName */
5688
5689         push_reg_sz(talloc_tos(), &buffer, global_myname());
5690         winreg_set_printer_dataex(p->mem_ctx,
5691                                   p->server_info,
5692                                   printer->info_2->sharename,
5693                                   SPOOL_DSSPOOLER_KEY,
5694                                   "serverName",
5695                                   REG_SZ,
5696                                   buffer.data,
5697                                   buffer.length);
5698         winreg_set_printer_dataex(p->mem_ctx,
5699                                   p->server_info,
5700                                   printer->info_2->sharename,
5701                                   SPOOL_DSSPOOLER_KEY,
5702                                   "shortServerName",
5703                                   REG_SZ,
5704                                   buffer.data,
5705                                   buffer.length);
5706
5707         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5708                  global_myname(), printer->info_2->sharename );
5709         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5710         winreg_set_printer_dataex(p->mem_ctx,
5711                                   p->server_info,
5712                                   printer->info_2->sharename,
5713                                   SPOOL_DSSPOOLER_KEY,
5714                                   "uNCName",
5715                                   REG_SZ,
5716                                   buffer.data,
5717                                   buffer.length);
5718
5719         /* Update printer info */
5720         result = mod_a_printer(printer, 2);
5721
5722 done:
5723         free_a_printer(&printer, 2);
5724         free_a_printer(&old_printer, 2);
5725
5726
5727         return result;
5728 }
5729
5730 /****************************************************************************
5731 ****************************************************************************/
5732 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5733                                            struct policy_handle *handle,
5734                                            struct spoolss_SetPrinterInfo7 *info7)
5735 {
5736 #ifdef HAVE_ADS
5737         int snum;
5738         Printer_entry *Printer;
5739
5740         if ( lp_security() != SEC_ADS ) {
5741                 return WERR_UNKNOWN_LEVEL;
5742         }
5743
5744         Printer = find_printer_index_by_hnd(p, handle);
5745
5746         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5747
5748         if (!Printer)
5749                 return WERR_BADFID;
5750
5751         if (!get_printer_snum(p, handle, &snum, NULL))
5752                 return WERR_BADFID;
5753
5754         nt_printer_publish(Printer, snum, info7->action);
5755
5756         return WERR_OK;
5757 #else
5758         return WERR_UNKNOWN_LEVEL;
5759 #endif
5760 }
5761
5762 /********************************************************************
5763  ********************************************************************/
5764
5765 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5766                                      struct spoolss_DeviceMode *devmode)
5767 {
5768         int snum;
5769         NT_PRINTER_INFO_LEVEL *printer = NULL;
5770         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5771         WERROR result;
5772
5773         DEBUG(8,("update_printer_devmode\n"));
5774
5775         result = WERR_OK;
5776
5777         if (!Printer) {
5778                 result = WERR_BADFID;
5779                 goto done;
5780         }
5781
5782         if (!get_printer_snum(p, handle, &snum, NULL)) {
5783                 result = WERR_BADFID;
5784                 goto done;
5785         }
5786
5787         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5788                 result = WERR_BADFID;
5789                 goto done;
5790         }
5791
5792         if (devmode) {
5793                 /* we have a valid devmode, copy it */
5794
5795                 DEBUGADD(8, ("update_printer: Copying the devicemode struct\n"));
5796                 result = copy_devicemode(printer->info_2, devmode,
5797                                          &printer->info_2->devmode);
5798                 if (!W_ERROR_IS_OK(result)) {
5799                         goto done;
5800                 }
5801         }
5802
5803         /* Check calling user has permission to update printer description */
5804
5805         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5806                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5807                 result = WERR_ACCESS_DENIED;
5808                 goto done;
5809         }
5810
5811
5812         /* Update printer info */
5813         result = mod_a_printer(printer, 2);
5814
5815 done:
5816         free_a_printer(&printer, 2);
5817
5818         return result;
5819 }
5820
5821
5822 /****************************************************************
5823  _spoolss_SetPrinter
5824 ****************************************************************/
5825
5826 WERROR _spoolss_SetPrinter(pipes_struct *p,
5827                            struct spoolss_SetPrinter *r)
5828 {
5829         WERROR result;
5830
5831         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5832
5833         if (!Printer) {
5834                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5835                         OUR_HANDLE(r->in.handle)));
5836                 return WERR_BADFID;
5837         }
5838
5839         /* check the level */
5840         switch (r->in.info_ctr->level) {
5841                 case 0:
5842                         return control_printer(r->in.handle, r->in.command, p);
5843                 case 2:
5844                         result = update_printer(p, r->in.handle,
5845                                                 r->in.info_ctr,
5846                                                 r->in.devmode_ctr->devmode);
5847                         if (!W_ERROR_IS_OK(result))
5848                                 return result;
5849                         if (r->in.secdesc_ctr->sd)
5850                                 result = update_printer_sec(r->in.handle, p,
5851                                                             r->in.secdesc_ctr);
5852                         return result;
5853                 case 3:
5854                         return update_printer_sec(r->in.handle, p,
5855                                                   r->in.secdesc_ctr);
5856                 case 7:
5857                         return publish_or_unpublish_printer(p, r->in.handle,
5858                                                             r->in.info_ctr->info.info7);
5859                 case 8:
5860                         return update_printer_devmode(p, r->in.handle,
5861                                                       r->in.devmode_ctr->devmode);
5862                 default:
5863                         return WERR_UNKNOWN_LEVEL;
5864         }
5865 }
5866
5867 /****************************************************************
5868  _spoolss_FindClosePrinterNotify
5869 ****************************************************************/
5870
5871 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5872                                        struct spoolss_FindClosePrinterNotify *r)
5873 {
5874         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5875
5876         if (!Printer) {
5877                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5878                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5879                 return WERR_BADFID;
5880         }
5881
5882         if (Printer->notify.client_connected == true) {
5883                 int snum = -1;
5884
5885                 if ( Printer->printer_type == SPLHND_SERVER)
5886                         snum = -1;
5887                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5888                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5889                         return WERR_BADFID;
5890
5891                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5892         }
5893
5894         Printer->notify.flags=0;
5895         Printer->notify.options=0;
5896         Printer->notify.localmachine[0]='\0';
5897         Printer->notify.printerlocal=0;
5898         TALLOC_FREE(Printer->notify.option);
5899         Printer->notify.client_connected = false;
5900
5901         return WERR_OK;
5902 }
5903
5904 /****************************************************************
5905  _spoolss_AddJob
5906 ****************************************************************/
5907
5908 WERROR _spoolss_AddJob(pipes_struct *p,
5909                        struct spoolss_AddJob *r)
5910 {
5911         if (!r->in.buffer && (r->in.offered != 0)) {
5912                 return WERR_INVALID_PARAM;
5913         }
5914
5915         /* this is what a NT server returns for AddJob. AddJob must fail on
5916          * non-local printers */
5917
5918         if (r->in.level != 1) {
5919                 return WERR_UNKNOWN_LEVEL;
5920         }
5921
5922         return WERR_INVALID_PARAM;
5923 }
5924
5925 /****************************************************************************
5926 fill_job_info1
5927 ****************************************************************************/
5928
5929 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5930                              struct spoolss_JobInfo1 *r,
5931                              const print_queue_struct *queue,
5932                              int position, int snum,
5933                              const NT_PRINTER_INFO_LEVEL *ntprinter)
5934 {
5935         struct tm *t;
5936
5937         t = gmtime(&queue->time);
5938
5939         r->job_id               = queue->job;
5940
5941         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
5942         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5943         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5944         W_ERROR_HAVE_NO_MEMORY(r->server_name);
5945         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
5946         W_ERROR_HAVE_NO_MEMORY(r->user_name);
5947         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
5948         W_ERROR_HAVE_NO_MEMORY(r->document_name);
5949         r->data_type            = talloc_strdup(mem_ctx, "RAW");
5950         W_ERROR_HAVE_NO_MEMORY(r->data_type);
5951         r->text_status          = talloc_strdup(mem_ctx, "");
5952         W_ERROR_HAVE_NO_MEMORY(r->text_status);
5953
5954         r->status               = nt_printj_status(queue->status);
5955         r->priority             = queue->priority;
5956         r->position             = position;
5957         r->total_pages          = queue->page_count;
5958         r->pages_printed        = 0; /* ??? */
5959
5960         init_systemtime(&r->submitted, t);
5961
5962         return WERR_OK;
5963 }
5964
5965 /****************************************************************************
5966 fill_job_info2
5967 ****************************************************************************/
5968
5969 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5970                              struct spoolss_JobInfo2 *r,
5971                              const print_queue_struct *queue,
5972                              int position, int snum,
5973                              const NT_PRINTER_INFO_LEVEL *ntprinter,
5974                              struct spoolss_DeviceMode *devmode)
5975 {
5976         struct tm *t;
5977
5978         t = gmtime(&queue->time);
5979
5980         r->job_id               = queue->job;
5981
5982         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
5983         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5984         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5985         W_ERROR_HAVE_NO_MEMORY(r->server_name);
5986         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
5987         W_ERROR_HAVE_NO_MEMORY(r->user_name);
5988         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
5989         W_ERROR_HAVE_NO_MEMORY(r->document_name);
5990         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
5991         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5992         r->data_type            = talloc_strdup(mem_ctx, "RAW");
5993         W_ERROR_HAVE_NO_MEMORY(r->data_type);
5994         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
5995         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5996         r->parameters           = talloc_strdup(mem_ctx, "");
5997         W_ERROR_HAVE_NO_MEMORY(r->parameters);
5998         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
5999         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6000
6001         r->devmode              = devmode;
6002
6003         r->text_status          = talloc_strdup(mem_ctx, "");
6004         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6005
6006         r->secdesc              = NULL;
6007
6008         r->status               = nt_printj_status(queue->status);
6009         r->priority             = queue->priority;
6010         r->position             = position;
6011         r->start_time           = 0;
6012         r->until_time           = 0;
6013         r->total_pages          = queue->page_count;
6014         r->size                 = queue->size;
6015         init_systemtime(&r->submitted, t);
6016         r->time                 = 0;
6017         r->pages_printed        = 0; /* ??? */
6018
6019         return WERR_OK;
6020 }
6021
6022 /****************************************************************************
6023 fill_job_info3
6024 ****************************************************************************/
6025
6026 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6027                              struct spoolss_JobInfo3 *r,
6028                              const print_queue_struct *queue,
6029                              const print_queue_struct *next_queue,
6030                              int position, int snum,
6031                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6032 {
6033         r->job_id               = queue->job;
6034         r->next_job_id          = 0;
6035         if (next_queue) {
6036                 r->next_job_id  = next_queue->job;
6037         }
6038         r->reserved             = 0;
6039
6040         return WERR_OK;
6041 }
6042
6043 /****************************************************************************
6044  Enumjobs at level 1.
6045 ****************************************************************************/
6046
6047 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6048                               const print_queue_struct *queue,
6049                               uint32_t num_queues, int snum,
6050                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6051                               union spoolss_JobInfo **info_p,
6052                               uint32_t *count)
6053 {
6054         union spoolss_JobInfo *info;
6055         int i;
6056         WERROR result = WERR_OK;
6057
6058         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6059         W_ERROR_HAVE_NO_MEMORY(info);
6060
6061         *count = num_queues;
6062
6063         for (i=0; i<*count; i++) {
6064                 result = fill_job_info1(info,
6065                                         &info[i].info1,
6066                                         &queue[i],
6067                                         i,
6068                                         snum,
6069                                         ntprinter);
6070                 if (!W_ERROR_IS_OK(result)) {
6071                         goto out;
6072                 }
6073         }
6074
6075  out:
6076         if (!W_ERROR_IS_OK(result)) {
6077                 TALLOC_FREE(info);
6078                 *count = 0;
6079                 return result;
6080         }
6081
6082         *info_p = info;
6083
6084         return WERR_OK;
6085 }
6086
6087 /****************************************************************************
6088  Enumjobs at level 2.
6089 ****************************************************************************/
6090
6091 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6092                               const print_queue_struct *queue,
6093                               uint32_t num_queues, int snum,
6094                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6095                               union spoolss_JobInfo **info_p,
6096                               uint32_t *count)
6097 {
6098         union spoolss_JobInfo *info;
6099         int i;
6100         WERROR result = WERR_OK;
6101
6102         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6103         W_ERROR_HAVE_NO_MEMORY(info);
6104
6105         *count = num_queues;
6106
6107         for (i=0; i<*count; i++) {
6108
6109                 struct spoolss_DeviceMode *devmode;
6110
6111                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6112                 if (!devmode) {
6113                         result = WERR_NOMEM;
6114                         goto out;
6115                 }
6116
6117                 result = fill_job_info2(info,
6118                                         &info[i].info2,
6119                                         &queue[i],
6120                                         i,
6121                                         snum,
6122                                         ntprinter,
6123                                         devmode);
6124                 if (!W_ERROR_IS_OK(result)) {
6125                         goto out;
6126                 }
6127         }
6128
6129  out:
6130         if (!W_ERROR_IS_OK(result)) {
6131                 TALLOC_FREE(info);
6132                 *count = 0;
6133                 return result;
6134         }
6135
6136         *info_p = info;
6137
6138         return WERR_OK;
6139 }
6140
6141 /****************************************************************************
6142  Enumjobs at level 3.
6143 ****************************************************************************/
6144
6145 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6146                               const print_queue_struct *queue,
6147                               uint32_t num_queues, int snum,
6148                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6149                               union spoolss_JobInfo **info_p,
6150                               uint32_t *count)
6151 {
6152         union spoolss_JobInfo *info;
6153         int i;
6154         WERROR result = WERR_OK;
6155
6156         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6157         W_ERROR_HAVE_NO_MEMORY(info);
6158
6159         *count = num_queues;
6160
6161         for (i=0; i<*count; i++) {
6162                 const print_queue_struct *next_queue = NULL;
6163
6164                 if (i+1 < *count) {
6165                         next_queue = &queue[i+1];
6166                 }
6167
6168                 result = fill_job_info3(info,
6169                                         &info[i].info3,
6170                                         &queue[i],
6171                                         next_queue,
6172                                         i,
6173                                         snum,
6174                                         ntprinter);
6175                 if (!W_ERROR_IS_OK(result)) {
6176                         goto out;
6177                 }
6178         }
6179
6180  out:
6181         if (!W_ERROR_IS_OK(result)) {
6182                 TALLOC_FREE(info);
6183                 *count = 0;
6184                 return result;
6185         }
6186
6187         *info_p = info;
6188
6189         return WERR_OK;
6190 }
6191
6192 /****************************************************************
6193  _spoolss_EnumJobs
6194 ****************************************************************/
6195
6196 WERROR _spoolss_EnumJobs(pipes_struct *p,
6197                          struct spoolss_EnumJobs *r)
6198 {
6199         WERROR result;
6200         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6201         int snum;
6202         print_status_struct prt_status;
6203         print_queue_struct *queue = NULL;
6204         uint32_t count;
6205
6206         /* that's an [in out] buffer */
6207
6208         if (!r->in.buffer && (r->in.offered != 0)) {
6209                 return WERR_INVALID_PARAM;
6210         }
6211
6212         DEBUG(4,("_spoolss_EnumJobs\n"));
6213
6214         *r->out.needed = 0;
6215         *r->out.count = 0;
6216         *r->out.info = NULL;
6217
6218         /* lookup the printer snum and tdb entry */
6219
6220         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6221                 return WERR_BADFID;
6222         }
6223
6224         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6225         if (!W_ERROR_IS_OK(result)) {
6226                 return result;
6227         }
6228
6229         count = print_queue_status(snum, &queue, &prt_status);
6230         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6231                 count, prt_status.status, prt_status.message));
6232
6233         if (count == 0) {
6234                 SAFE_FREE(queue);
6235                 free_a_printer(&ntprinter, 2);
6236                 return WERR_OK;
6237         }
6238
6239         switch (r->in.level) {
6240         case 1:
6241                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6242                                          ntprinter, r->out.info, r->out.count);
6243                 break;
6244         case 2:
6245                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6246                                          ntprinter, r->out.info, r->out.count);
6247                 break;
6248         case 3:
6249                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6250                                          ntprinter, r->out.info, r->out.count);
6251                 break;
6252         default:
6253                 result = WERR_UNKNOWN_LEVEL;
6254                 break;
6255         }
6256
6257         SAFE_FREE(queue);
6258         free_a_printer(&ntprinter, 2);
6259
6260         if (!W_ERROR_IS_OK(result)) {
6261                 return result;
6262         }
6263
6264         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6265                                                      spoolss_EnumJobs, 
6266                                                      *r->out.info, r->in.level,
6267                                                      *r->out.count);
6268         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6269         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6270
6271         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6272 }
6273
6274 /****************************************************************
6275  _spoolss_ScheduleJob
6276 ****************************************************************/
6277
6278 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6279                             struct spoolss_ScheduleJob *r)
6280 {
6281         return WERR_OK;
6282 }
6283
6284 /****************************************************************
6285 ****************************************************************/
6286
6287 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6288                                const char *printer_name,
6289                                uint32_t job_id,
6290                                struct spoolss_SetJobInfo1 *r)
6291 {
6292         char *old_doc_name;
6293
6294         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6295                 return WERR_BADFID;
6296         }
6297
6298         if (strequal(old_doc_name, r->document_name)) {
6299                 return WERR_OK;
6300         }
6301
6302         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6303                 return WERR_BADFID;
6304         }
6305
6306         return WERR_OK;
6307 }
6308
6309 /****************************************************************
6310  _spoolss_SetJob
6311 ****************************************************************/
6312
6313 WERROR _spoolss_SetJob(pipes_struct *p,
6314                        struct spoolss_SetJob *r)
6315 {
6316         int snum;
6317         WERROR errcode = WERR_BADFUNC;
6318
6319         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6320                 return WERR_BADFID;
6321         }
6322
6323         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6324                 return WERR_INVALID_PRINTER_NAME;
6325         }
6326
6327         switch (r->in.command) {
6328         case SPOOLSS_JOB_CONTROL_CANCEL:
6329         case SPOOLSS_JOB_CONTROL_DELETE:
6330                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6331                         errcode = WERR_OK;
6332                 }
6333                 break;
6334         case SPOOLSS_JOB_CONTROL_PAUSE:
6335                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6336                         errcode = WERR_OK;
6337                 }
6338                 break;
6339         case SPOOLSS_JOB_CONTROL_RESTART:
6340         case SPOOLSS_JOB_CONTROL_RESUME:
6341                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6342                         errcode = WERR_OK;
6343                 }
6344                 break;
6345         case 0:
6346                 errcode = WERR_OK;
6347                 break;
6348         default:
6349                 return WERR_UNKNOWN_LEVEL;
6350         }
6351
6352         if (!W_ERROR_IS_OK(errcode)) {
6353                 return errcode;
6354         }
6355
6356         if (r->in.ctr == NULL) {
6357                 return errcode;
6358         }
6359
6360         switch (r->in.ctr->level) {
6361         case 1:
6362                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6363                                            r->in.job_id,
6364                                            r->in.ctr->info.info1);
6365                 break;
6366         case 2:
6367         case 3:
6368         case 4:
6369         default:
6370                 return WERR_UNKNOWN_LEVEL;
6371         }
6372
6373         return errcode;
6374 }
6375
6376 /****************************************************************************
6377  Enumerates all printer drivers by level and architecture.
6378 ****************************************************************************/
6379
6380 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6381                                                        const char *servername,
6382                                                        const char *architecture,
6383                                                        uint32_t level,
6384                                                        union spoolss_DriverInfo **info_p,
6385                                                        uint32_t *count_p)
6386 {
6387         int i;
6388         int ndrivers;
6389         uint32_t version;
6390         fstring *list = NULL;
6391         struct spoolss_DriverInfo8 *driver;
6392         union spoolss_DriverInfo *info = NULL;
6393         uint32_t count = 0;
6394         WERROR result = WERR_OK;
6395
6396         *count_p = 0;
6397         *info_p = NULL;
6398
6399         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6400                 list = NULL;
6401                 ndrivers = get_ntdrivers(&list, architecture, version);
6402                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6403                         ndrivers, architecture, version));
6404
6405                 if (ndrivers == -1) {
6406                         result = WERR_NOMEM;
6407                         goto out;
6408                 }
6409
6410                 if (ndrivers != 0) {
6411                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6412                                                     union spoolss_DriverInfo,
6413                                                     count + ndrivers);
6414                         if (!info) {
6415                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6416                                         "failed to enlarge driver info buffer!\n"));
6417                                 result = WERR_NOMEM;
6418                                 goto out;
6419                         }
6420                 }
6421
6422                 for (i=0; i<ndrivers; i++) {
6423                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6424                         ZERO_STRUCT(driver);
6425                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6426                                                       architecture, version);
6427                         if (!W_ERROR_IS_OK(result)) {
6428                                 goto out;
6429                         }
6430
6431                         switch (level) {
6432                         case 1:
6433                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6434                                                                    driver, servername);
6435                                 break;
6436                         case 2:
6437                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6438                                                                    driver, servername);
6439                                 break;
6440                         case 3:
6441                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6442                                                                    driver, servername);
6443                                 break;
6444                         case 4:
6445                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6446                                                                    driver, servername);
6447                                 break;
6448                         case 5:
6449                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6450                                                                    driver, servername);
6451                                 break;
6452                         case 6:
6453                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6454                                                                    driver, servername);
6455                                 break;
6456                         case 8:
6457                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6458                                                                    driver, servername);
6459                                 break;
6460                         default:
6461                                 result = WERR_UNKNOWN_LEVEL;
6462                                 break;
6463                         }
6464
6465                         free_a_printer_driver(driver);
6466
6467                         if (!W_ERROR_IS_OK(result)) {
6468                                 goto out;
6469                         }
6470                 }
6471
6472                 count += ndrivers;
6473                 SAFE_FREE(list);
6474         }
6475
6476  out:
6477         SAFE_FREE(list);
6478
6479         if (!W_ERROR_IS_OK(result)) {
6480                 TALLOC_FREE(info);
6481                 return result;
6482         }
6483
6484         *info_p = info;
6485         *count_p = count;
6486
6487         return WERR_OK;
6488 }
6489
6490 /****************************************************************************
6491  Enumerates all printer drivers by level.
6492 ****************************************************************************/
6493
6494 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6495                                        const char *servername,
6496                                        const char *architecture,
6497                                        uint32_t level,
6498                                        union spoolss_DriverInfo **info_p,
6499                                        uint32_t *count_p)
6500 {
6501         uint32_t a,i;
6502         WERROR result = WERR_OK;
6503
6504         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6505
6506                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6507
6508                         union spoolss_DriverInfo *info = NULL;
6509                         uint32_t count = 0;
6510
6511                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6512                                                                           servername,
6513                                                                           archi_table[a].long_archi,
6514                                                                           level,
6515                                                                           &info,
6516                                                                           &count);
6517                         if (!W_ERROR_IS_OK(result)) {
6518                                 continue;
6519                         }
6520
6521                         for (i=0; i < count; i++) {
6522                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6523                                              info[i], info_p, count_p);
6524                         }
6525                 }
6526
6527                 return result;
6528         }
6529
6530         return enumprinterdrivers_level_by_architecture(mem_ctx,
6531                                                         servername,
6532                                                         architecture,
6533                                                         level,
6534                                                         info_p,
6535                                                         count_p);
6536 }
6537
6538 /****************************************************************
6539  _spoolss_EnumPrinterDrivers
6540 ****************************************************************/
6541
6542 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6543                                    struct spoolss_EnumPrinterDrivers *r)
6544 {
6545         const char *cservername;
6546         WERROR result;
6547
6548         /* that's an [in out] buffer */
6549
6550         if (!r->in.buffer && (r->in.offered != 0)) {
6551                 return WERR_INVALID_PARAM;
6552         }
6553
6554         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6555
6556         *r->out.needed = 0;
6557         *r->out.count = 0;
6558         *r->out.info = NULL;
6559
6560         cservername = canon_servername(r->in.server);
6561
6562         if (!is_myname_or_ipaddr(cservername)) {
6563                 return WERR_UNKNOWN_PRINTER_DRIVER;
6564         }
6565
6566         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6567                                           r->in.environment,
6568                                           r->in.level,
6569                                           r->out.info,
6570                                           r->out.count);
6571         if (!W_ERROR_IS_OK(result)) {
6572                 return result;
6573         }
6574
6575         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6576                                                      spoolss_EnumPrinterDrivers, 
6577                                                      *r->out.info, r->in.level,
6578                                                      *r->out.count);
6579         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6580         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6581
6582         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6583 }
6584
6585 /****************************************************************************
6586 ****************************************************************************/
6587
6588 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6589                                struct spoolss_FormInfo1 *r,
6590                                const nt_forms_struct *form)
6591 {
6592         r->form_name    = talloc_strdup(mem_ctx, form->name);
6593         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6594
6595         r->flags        = form->flag;
6596         r->size.width   = form->width;
6597         r->size.height  = form->length;
6598         r->area.left    = form->left;
6599         r->area.top     = form->top;
6600         r->area.right   = form->right;
6601         r->area.bottom  = form->bottom;
6602
6603         return WERR_OK;
6604 }
6605
6606 /****************************************************************
6607  spoolss_enumforms_level1
6608 ****************************************************************/
6609
6610 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6611                                        const nt_forms_struct *builtin_forms,
6612                                        uint32_t num_builtin_forms,
6613                                        const nt_forms_struct *user_forms,
6614                                        uint32_t num_user_forms,
6615                                        union spoolss_FormInfo **info_p,
6616                                        uint32_t *count)
6617 {
6618         union spoolss_FormInfo *info;
6619         WERROR result = WERR_OK;
6620         int i;
6621
6622         *count = num_builtin_forms + num_user_forms;
6623
6624         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6625         W_ERROR_HAVE_NO_MEMORY(info);
6626
6627         /* construct the list of form structures */
6628         for (i=0; i<num_builtin_forms; i++) {
6629                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6630                 result = fill_form_info_1(info, &info[i].info1,
6631                                           &builtin_forms[i]);
6632                 if (!W_ERROR_IS_OK(result)) {
6633                         goto out;
6634                 }
6635         }
6636
6637         for (i=0; i<num_user_forms; i++) {
6638                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6639                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6640                                           &user_forms[i]);
6641                 if (!W_ERROR_IS_OK(result)) {
6642                         goto out;
6643                 }
6644         }
6645
6646  out:
6647         if (!W_ERROR_IS_OK(result)) {
6648                 TALLOC_FREE(info);
6649                 *count = 0;
6650                 return result;
6651         }
6652
6653         *info_p = info;
6654
6655         return WERR_OK;
6656 }
6657
6658 /****************************************************************
6659  _spoolss_EnumForms
6660 ****************************************************************/
6661
6662 WERROR _spoolss_EnumForms(pipes_struct *p,
6663                           struct spoolss_EnumForms *r)
6664 {
6665         WERROR result;
6666         nt_forms_struct *user_forms = NULL;
6667         nt_forms_struct *builtin_forms = NULL;
6668         uint32_t num_user_forms;
6669         uint32_t num_builtin_forms;
6670
6671         *r->out.count = 0;
6672         *r->out.needed = 0;
6673         *r->out.info = NULL;
6674
6675         /* that's an [in out] buffer */
6676
6677         if (!r->in.buffer && (r->in.offered != 0) ) {
6678                 return WERR_INVALID_PARAM;
6679         }
6680
6681         DEBUG(4,("_spoolss_EnumForms\n"));
6682         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6683         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6684
6685         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6686         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6687         num_user_forms = get_ntforms(&user_forms);
6688         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6689
6690         if (num_user_forms + num_builtin_forms == 0) {
6691                 SAFE_FREE(builtin_forms);
6692                 SAFE_FREE(user_forms);
6693                 return WERR_NO_MORE_ITEMS;
6694         }
6695
6696         switch (r->in.level) {
6697         case 1:
6698                 result = spoolss_enumforms_level1(p->mem_ctx,
6699                                                   builtin_forms,
6700                                                   num_builtin_forms,
6701                                                   user_forms,
6702                                                   num_user_forms,
6703                                                   r->out.info,
6704                                                   r->out.count);
6705                 break;
6706         default:
6707                 result = WERR_UNKNOWN_LEVEL;
6708                 break;
6709         }
6710
6711         SAFE_FREE(user_forms);
6712         SAFE_FREE(builtin_forms);
6713
6714         if (!W_ERROR_IS_OK(result)) {
6715                 return result;
6716         }
6717
6718         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6719                                                      spoolss_EnumForms, 
6720                                                      *r->out.info, r->in.level,
6721                                                      *r->out.count);
6722         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6723         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6724
6725         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6726 }
6727
6728 /****************************************************************
6729 ****************************************************************/
6730
6731 static WERROR find_form_byname(const char *name,
6732                                nt_forms_struct *form)
6733 {
6734         nt_forms_struct *list = NULL;
6735         int num_forms = 0, i = 0;
6736
6737         if (get_a_builtin_ntform_by_string(name, form)) {
6738                 return WERR_OK;
6739         }
6740
6741         num_forms = get_ntforms(&list);
6742         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6743
6744         if (num_forms == 0) {
6745                 return WERR_BADFID;
6746         }
6747
6748         /* Check if the requested name is in the list of form structures */
6749         for (i = 0; i < num_forms; i++) {
6750
6751                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6752
6753                 if (strequal(name, list[i].name)) {
6754                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6755                         *form = list[i];
6756                         SAFE_FREE(list);
6757                         return WERR_OK;
6758                 }
6759         }
6760
6761         SAFE_FREE(list);
6762
6763         return WERR_BADFID;
6764 }
6765
6766 /****************************************************************
6767  _spoolss_GetForm
6768 ****************************************************************/
6769
6770 WERROR _spoolss_GetForm(pipes_struct *p,
6771                         struct spoolss_GetForm *r)
6772 {
6773         WERROR result;
6774         nt_forms_struct form;
6775
6776         /* that's an [in out] buffer */
6777
6778         if (!r->in.buffer && (r->in.offered != 0)) {
6779                 return WERR_INVALID_PARAM;
6780         }
6781
6782         DEBUG(4,("_spoolss_GetForm\n"));
6783         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6784         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6785
6786         result = find_form_byname(r->in.form_name, &form);
6787         if (!W_ERROR_IS_OK(result)) {
6788                 TALLOC_FREE(r->out.info);
6789                 return result;
6790         }
6791
6792         switch (r->in.level) {
6793         case 1:
6794                 result = fill_form_info_1(p->mem_ctx,
6795                                           &r->out.info->info1,
6796                                           &form);
6797                 break;
6798
6799         default:
6800                 result = WERR_UNKNOWN_LEVEL;
6801                 break;
6802         }
6803
6804         if (!W_ERROR_IS_OK(result)) {
6805                 TALLOC_FREE(r->out.info);
6806                 return result;
6807         }
6808
6809         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6810                                                r->out.info, r->in.level);
6811         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6812
6813         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6814 }
6815
6816 /****************************************************************************
6817 ****************************************************************************/
6818
6819 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6820                           struct spoolss_PortInfo1 *r,
6821                           const char *name)
6822 {
6823         r->port_name = talloc_strdup(mem_ctx, name);
6824         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6825
6826         return WERR_OK;
6827 }
6828
6829 /****************************************************************************
6830  TODO: This probably needs distinguish between TCP/IP and Local ports
6831  somehow.
6832 ****************************************************************************/
6833
6834 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6835                           struct spoolss_PortInfo2 *r,
6836                           const char *name)
6837 {
6838         r->port_name = talloc_strdup(mem_ctx, name);
6839         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6840
6841         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6842         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6843
6844         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6845         W_ERROR_HAVE_NO_MEMORY(r->description);
6846
6847         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6848         r->reserved = 0;
6849
6850         return WERR_OK;
6851 }
6852
6853
6854 /****************************************************************************
6855  wrapper around the enumer ports command
6856 ****************************************************************************/
6857
6858 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6859 {
6860         char *cmd = lp_enumports_cmd();
6861         char **qlines = NULL;
6862         char *command = NULL;
6863         int numlines;
6864         int ret;
6865         int fd;
6866
6867         *count = 0;
6868         *lines = NULL;
6869
6870         /* if no hook then just fill in the default port */
6871
6872         if ( !*cmd ) {
6873                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6874                         return WERR_NOMEM;
6875                 }
6876                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6877                         TALLOC_FREE(qlines);
6878                         return WERR_NOMEM;
6879                 }
6880                 qlines[1] = NULL;
6881                 numlines = 1;
6882         }
6883         else {
6884                 /* we have a valid enumport command */
6885
6886                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6887                 if (!command) {
6888                         return WERR_NOMEM;
6889                 }
6890
6891                 DEBUG(10,("Running [%s]\n", command));
6892                 ret = smbrun(command, &fd);
6893                 DEBUG(10,("Returned [%d]\n", ret));
6894                 TALLOC_FREE(command);
6895                 if (ret != 0) {
6896                         if (fd != -1) {
6897                                 close(fd);
6898                         }
6899                         return WERR_ACCESS_DENIED;
6900                 }
6901
6902                 numlines = 0;
6903                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6904                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6905                 close(fd);
6906         }
6907
6908         *count = numlines;
6909         *lines = qlines;
6910
6911         return WERR_OK;
6912 }
6913
6914 /****************************************************************************
6915  enumports level 1.
6916 ****************************************************************************/
6917
6918 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6919                                 union spoolss_PortInfo **info_p,
6920                                 uint32_t *count)
6921 {
6922         union spoolss_PortInfo *info = NULL;
6923         int i=0;
6924         WERROR result = WERR_OK;
6925         char **qlines = NULL;
6926         int numlines = 0;
6927
6928         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6929         if (!W_ERROR_IS_OK(result)) {
6930                 goto out;
6931         }
6932
6933         if (numlines) {
6934                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6935                 if (!info) {
6936                         DEBUG(10,("Returning WERR_NOMEM\n"));
6937                         result = WERR_NOMEM;
6938                         goto out;
6939                 }
6940
6941                 for (i=0; i<numlines; i++) {
6942                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6943                         result = fill_port_1(info, &info[i].info1, qlines[i]);
6944                         if (!W_ERROR_IS_OK(result)) {
6945                                 goto out;
6946                         }
6947                 }
6948         }
6949         TALLOC_FREE(qlines);
6950
6951 out:
6952         if (!W_ERROR_IS_OK(result)) {
6953                 TALLOC_FREE(info);
6954                 TALLOC_FREE(qlines);
6955                 *count = 0;
6956                 *info_p = NULL;
6957                 return result;
6958         }
6959
6960         *info_p = info;
6961         *count = numlines;
6962
6963         return WERR_OK;
6964 }
6965
6966 /****************************************************************************
6967  enumports level 2.
6968 ****************************************************************************/
6969
6970 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6971                                 union spoolss_PortInfo **info_p,
6972                                 uint32_t *count)
6973 {
6974         union spoolss_PortInfo *info = NULL;
6975         int i=0;
6976         WERROR result = WERR_OK;
6977         char **qlines = NULL;
6978         int numlines = 0;
6979
6980         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6981         if (!W_ERROR_IS_OK(result)) {
6982                 goto out;
6983         }
6984
6985         if (numlines) {
6986                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6987                 if (!info) {
6988                         DEBUG(10,("Returning WERR_NOMEM\n"));
6989                         result = WERR_NOMEM;
6990                         goto out;
6991                 }
6992
6993                 for (i=0; i<numlines; i++) {
6994                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6995                         result = fill_port_2(info, &info[i].info2, qlines[i]);
6996                         if (!W_ERROR_IS_OK(result)) {
6997                                 goto out;
6998                         }
6999                 }
7000         }
7001         TALLOC_FREE(qlines);
7002
7003 out:
7004         if (!W_ERROR_IS_OK(result)) {
7005                 TALLOC_FREE(info);
7006                 TALLOC_FREE(qlines);
7007                 *count = 0;
7008                 *info_p = NULL;
7009                 return result;
7010         }
7011
7012         *info_p = info;
7013         *count = numlines;
7014
7015         return WERR_OK;
7016 }
7017
7018 /****************************************************************
7019  _spoolss_EnumPorts
7020 ****************************************************************/
7021
7022 WERROR _spoolss_EnumPorts(pipes_struct *p,
7023                           struct spoolss_EnumPorts *r)
7024 {
7025         WERROR result;
7026
7027         /* that's an [in out] buffer */
7028
7029         if (!r->in.buffer && (r->in.offered != 0)) {
7030                 return WERR_INVALID_PARAM;
7031         }
7032
7033         DEBUG(4,("_spoolss_EnumPorts\n"));
7034
7035         *r->out.count = 0;
7036         *r->out.needed = 0;
7037         *r->out.info = NULL;
7038
7039         switch (r->in.level) {
7040         case 1:
7041                 result = enumports_level_1(p->mem_ctx, r->out.info,
7042                                            r->out.count);
7043                 break;
7044         case 2:
7045                 result = enumports_level_2(p->mem_ctx, r->out.info,
7046                                            r->out.count);
7047                 break;
7048         default:
7049                 return WERR_UNKNOWN_LEVEL;
7050         }
7051
7052         if (!W_ERROR_IS_OK(result)) {
7053                 return result;
7054         }
7055
7056         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7057                                                      spoolss_EnumPorts, 
7058                                                      *r->out.info, r->in.level,
7059                                                      *r->out.count);
7060         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7061         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7062
7063         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7064 }
7065
7066 /****************************************************************************
7067 ****************************************************************************/
7068
7069 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7070                                            const char *server,
7071                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7072                                            struct spoolss_DeviceMode *devmode,
7073                                            struct security_descriptor *sec_desc,
7074                                            struct spoolss_UserLevelCtr *user_ctr,
7075                                            struct policy_handle *handle)
7076 {
7077         NT_PRINTER_INFO_LEVEL *printer = NULL;
7078         fstring name;
7079         int     snum;
7080         WERROR err = WERR_OK;
7081
7082         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7083                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7084                 return WERR_NOMEM;
7085         }
7086
7087         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7088         if (!convert_printer_info(info_ctr, printer)) {
7089                 free_a_printer(&printer, 2);
7090                 return WERR_NOMEM;
7091         }
7092
7093         /* samba does not have a concept of local, non-shared printers yet, so
7094          * make sure we always setup sharename - gd */
7095         if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7096                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7097                         "no sharename has been set, setting printername %s as sharename\n",
7098                         printer->info_2->printername));
7099                 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7100         }
7101
7102         /* check to see if the printer already exists */
7103
7104         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7105                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7106                         printer->info_2->sharename));
7107                 free_a_printer(&printer, 2);
7108                 return WERR_PRINTER_ALREADY_EXISTS;
7109         }
7110
7111         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7112                 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7113                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7114                                 printer->info_2->printername));
7115                         free_a_printer(&printer, 2);
7116                         return WERR_PRINTER_ALREADY_EXISTS;
7117                 }
7118         }
7119
7120         /* validate printer info struct */
7121         if (!info_ctr->info.info2->printername ||
7122             strlen(info_ctr->info.info2->printername) == 0) {
7123                 free_a_printer(&printer,2);
7124                 return WERR_INVALID_PRINTER_NAME;
7125         }
7126         if (!info_ctr->info.info2->portname ||
7127             strlen(info_ctr->info.info2->portname) == 0) {
7128                 free_a_printer(&printer,2);
7129                 return WERR_UNKNOWN_PORT;
7130         }
7131         if (!info_ctr->info.info2->drivername ||
7132             strlen(info_ctr->info.info2->drivername) == 0) {
7133                 free_a_printer(&printer,2);
7134                 return WERR_UNKNOWN_PRINTER_DRIVER;
7135         }
7136         if (!info_ctr->info.info2->printprocessor ||
7137             strlen(info_ctr->info.info2->printprocessor) == 0) {
7138                 free_a_printer(&printer,2);
7139                 return WERR_UNKNOWN_PRINTPROCESSOR;
7140         }
7141
7142         /* FIXME!!!  smbd should check to see if the driver is installed before
7143            trying to add a printer like this  --jerry */
7144
7145         if (*lp_addprinter_cmd() ) {
7146                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7147                                        printer) ) {
7148                         free_a_printer(&printer,2);
7149                         return WERR_ACCESS_DENIED;
7150                 }
7151         } else {
7152                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7153                         "smb.conf parameter \"addprinter command\" is defined. This"
7154                         "parameter must exist for this call to succeed\n",
7155                         printer->info_2->sharename ));
7156         }
7157
7158         /* use our primary netbios name since get_a_printer() will convert
7159            it to what the client expects on a case by case basis */
7160
7161         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7162              printer->info_2->sharename);
7163
7164
7165         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7166                 free_a_printer(&printer,2);
7167                 return WERR_ACCESS_DENIED;
7168         }
7169
7170         /* you must be a printer admin to add a new printer */
7171         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7172                 free_a_printer(&printer,2);
7173                 return WERR_ACCESS_DENIED;
7174         }
7175
7176         /*
7177          * Do sanity check on the requested changes for Samba.
7178          */
7179
7180         if (!check_printer_ok(printer->info_2, snum)) {
7181                 free_a_printer(&printer,2);
7182                 return WERR_INVALID_PARAM;
7183         }
7184
7185         /*
7186          * When a printer is created, the drivername bound to the printer is used
7187          * to lookup previously saved driver initialization info, which is then
7188          * bound to the new printer, simulating what happens in the Windows arch.
7189          */
7190
7191         if (devmode)
7192         {
7193                 /* A valid devmode was included, convert and link it
7194                 */
7195                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7196
7197                 err = copy_devicemode(printer, devmode,
7198                                       &printer->info_2->devmode);
7199                 if (!W_ERROR_IS_OK(err)) {
7200                         return err;
7201                 }
7202         }
7203
7204         /* write the ASCII on disk */
7205         err = mod_a_printer(printer, 2);
7206         if (!W_ERROR_IS_OK(err)) {
7207                 free_a_printer(&printer,2);
7208                 return err;
7209         }
7210
7211         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7212                 /* Handle open failed - remove addition. */
7213                 del_a_printer(printer->info_2->sharename);
7214                 free_a_printer(&printer,2);
7215                 ZERO_STRUCTP(handle);
7216                 return WERR_ACCESS_DENIED;
7217         }
7218
7219         update_c_setprinter(false);
7220         free_a_printer(&printer,2);
7221
7222         return WERR_OK;
7223 }
7224
7225 /****************************************************************
7226  _spoolss_AddPrinterEx
7227 ****************************************************************/
7228
7229 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7230                              struct spoolss_AddPrinterEx *r)
7231 {
7232         switch (r->in.info_ctr->level) {
7233         case 1:
7234                 /* we don't handle yet */
7235                 /* but I know what to do ... */
7236                 return WERR_UNKNOWN_LEVEL;
7237         case 2:
7238                 return spoolss_addprinterex_level_2(p, r->in.server,
7239                                                     r->in.info_ctr,
7240                                                     r->in.devmode_ctr->devmode,
7241                                                     r->in.secdesc_ctr->sd,
7242                                                     r->in.userlevel_ctr,
7243                                                     r->out.handle);
7244         default:
7245                 return WERR_UNKNOWN_LEVEL;
7246         }
7247 }
7248
7249 /****************************************************************
7250  _spoolss_AddPrinter
7251 ****************************************************************/
7252
7253 WERROR _spoolss_AddPrinter(pipes_struct *p,
7254                            struct spoolss_AddPrinter *r)
7255 {
7256         struct spoolss_AddPrinterEx a;
7257         struct spoolss_UserLevelCtr userlevel_ctr;
7258
7259         ZERO_STRUCT(userlevel_ctr);
7260
7261         userlevel_ctr.level = 1;
7262
7263         a.in.server             = r->in.server;
7264         a.in.info_ctr           = r->in.info_ctr;
7265         a.in.devmode_ctr        = r->in.devmode_ctr;
7266         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7267         a.in.userlevel_ctr      = &userlevel_ctr;
7268         a.out.handle            = r->out.handle;
7269
7270         return _spoolss_AddPrinterEx(p, &a);
7271 }
7272
7273 /****************************************************************
7274  _spoolss_AddPrinterDriverEx
7275 ****************************************************************/
7276
7277 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7278                                    struct spoolss_AddPrinterDriverEx *r)
7279 {
7280         WERROR err = WERR_OK;
7281         char *driver_name = NULL;
7282         uint32_t version;
7283         const char *fn;
7284
7285         switch (p->opnum) {
7286                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7287                         fn = "_spoolss_AddPrinterDriver";
7288                         break;
7289                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7290                         fn = "_spoolss_AddPrinterDriverEx";
7291                         break;
7292                 default:
7293                         return WERR_INVALID_PARAM;
7294         }
7295
7296         /*
7297          * we only support the semantics of AddPrinterDriver()
7298          * i.e. only copy files that are newer than existing ones
7299          */
7300
7301         if (r->in.flags == 0) {
7302                 return WERR_INVALID_PARAM;
7303         }
7304
7305         if (r->in.flags != APD_COPY_NEW_FILES) {
7306                 return WERR_ACCESS_DENIED;
7307         }
7308
7309         /* FIXME */
7310         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7311                 /* Clever hack from Martin Zielinski <mz@seh.de>
7312                  * to allow downgrade from level 8 (Vista).
7313                  */
7314                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7315                         r->in.info_ctr->level));
7316                 return WERR_UNKNOWN_LEVEL;
7317         }
7318
7319         DEBUG(5,("Cleaning driver's information\n"));
7320         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7321         if (!W_ERROR_IS_OK(err))
7322                 goto done;
7323
7324         DEBUG(5,("Moving driver to final destination\n"));
7325         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7326                                                               &err)) ) {
7327                 goto done;
7328         }
7329
7330         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7331                 err = WERR_ACCESS_DENIED;
7332                 goto done;
7333         }
7334
7335         /*
7336          * I think this is where he DrvUpgradePrinter() hook would be
7337          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7338          * server.  Right now, we just need to send ourselves a message
7339          * to update each printer bound to this driver.   --jerry
7340          */
7341
7342         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7343                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7344                         fn, driver_name));
7345         }
7346
7347 done:
7348         return err;
7349 }
7350
7351 /****************************************************************
7352  _spoolss_AddPrinterDriver
7353 ****************************************************************/
7354
7355 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7356                                  struct spoolss_AddPrinterDriver *r)
7357 {
7358         struct spoolss_AddPrinterDriverEx a;
7359
7360         switch (r->in.info_ctr->level) {
7361         case 2:
7362         case 3:
7363         case 4:
7364         case 5:
7365                 break;
7366         default:
7367                 return WERR_UNKNOWN_LEVEL;
7368         }
7369
7370         a.in.servername         = r->in.servername;
7371         a.in.info_ctr           = r->in.info_ctr;
7372         a.in.flags              = APD_COPY_NEW_FILES;
7373
7374         return _spoolss_AddPrinterDriverEx(p, &a);
7375 }
7376
7377 /****************************************************************************
7378 ****************************************************************************/
7379
7380 struct _spoolss_paths {
7381         int type;
7382         const char *share;
7383         const char *dir;
7384 };
7385
7386 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7387
7388 static const struct _spoolss_paths spoolss_paths[]= {
7389         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7390         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7391 };
7392
7393 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7394                                           const char *servername,
7395                                           const char *environment,
7396                                           int component,
7397                                           char **path)
7398 {
7399         const char *pservername = NULL;
7400         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7401         const char *short_archi;
7402
7403         *path = NULL;
7404
7405         /* environment may be empty */
7406         if (environment && strlen(environment)) {
7407                 long_archi = environment;
7408         }
7409
7410         /* servername may be empty */
7411         if (servername && strlen(servername)) {
7412                 pservername = canon_servername(servername);
7413
7414                 if (!is_myname_or_ipaddr(pservername)) {
7415                         return WERR_INVALID_PARAM;
7416                 }
7417         }
7418
7419         if (!(short_archi = get_short_archi(long_archi))) {
7420                 return WERR_INVALID_ENVIRONMENT;
7421         }
7422
7423         switch (component) {
7424         case SPOOLSS_PRTPROCS_PATH:
7425         case SPOOLSS_DRIVER_PATH:
7426                 if (pservername) {
7427                         *path = talloc_asprintf(mem_ctx,
7428                                         "\\\\%s\\%s\\%s",
7429                                         pservername,
7430                                         spoolss_paths[component].share,
7431                                         short_archi);
7432                 } else {
7433                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7434                                         SPOOLSS_DEFAULT_SERVER_PATH,
7435                                         spoolss_paths[component].dir,
7436                                         short_archi);
7437                 }
7438                 break;
7439         default:
7440                 return WERR_INVALID_PARAM;
7441         }
7442
7443         if (!*path) {
7444                 return WERR_NOMEM;
7445         }
7446
7447         return WERR_OK;
7448 }
7449
7450 /****************************************************************************
7451 ****************************************************************************/
7452
7453 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7454                                           const char *servername,
7455                                           const char *environment,
7456                                           struct spoolss_DriverDirectoryInfo1 *r)
7457 {
7458         WERROR werr;
7459         char *path = NULL;
7460
7461         werr = compose_spoolss_server_path(mem_ctx,
7462                                            servername,
7463                                            environment,
7464                                            SPOOLSS_DRIVER_PATH,
7465                                            &path);
7466         if (!W_ERROR_IS_OK(werr)) {
7467                 return werr;
7468         }
7469
7470         DEBUG(4,("printer driver directory: [%s]\n", path));
7471
7472         r->directory_name = path;
7473
7474         return WERR_OK;
7475 }
7476
7477 /****************************************************************
7478  _spoolss_GetPrinterDriverDirectory
7479 ****************************************************************/
7480
7481 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7482                                           struct spoolss_GetPrinterDriverDirectory *r)
7483 {
7484         WERROR werror;
7485
7486         /* that's an [in out] buffer */
7487
7488         if (!r->in.buffer && (r->in.offered != 0)) {
7489                 return WERR_INVALID_PARAM;
7490         }
7491
7492         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7493                 r->in.level));
7494
7495         *r->out.needed = 0;
7496
7497         /* r->in.level is ignored */
7498
7499         werror = getprinterdriverdir_level_1(p->mem_ctx,
7500                                              r->in.server,
7501                                              r->in.environment,
7502                                              &r->out.info->info1);
7503         if (!W_ERROR_IS_OK(werror)) {
7504                 TALLOC_FREE(r->out.info);
7505                 return werror;
7506         }
7507
7508         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7509                                                r->out.info, r->in.level);
7510         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7511
7512         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7513 }
7514
7515 /****************************************************************
7516  _spoolss_EnumPrinterData
7517 ****************************************************************/
7518
7519 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7520                                 struct spoolss_EnumPrinterData *r)
7521 {
7522         WERROR result;
7523         struct spoolss_EnumPrinterDataEx r2;
7524         uint32_t count;
7525         struct spoolss_PrinterEnumValues *info, *val = NULL;
7526         uint32_t needed;
7527
7528         r2.in.handle    = r->in.handle;
7529         r2.in.key_name  = "PrinterDriverData";
7530         r2.in.offered   = 0;
7531         r2.out.count    = &count;
7532         r2.out.info     = &info;
7533         r2.out.needed   = &needed;
7534
7535         result = _spoolss_EnumPrinterDataEx(p, &r2);
7536         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7537                 r2.in.offered = needed;
7538                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7539         }
7540         if (!W_ERROR_IS_OK(result)) {
7541                 return result;
7542         }
7543
7544         /*
7545          * The NT machine wants to know the biggest size of value and data
7546          *
7547          * cf: MSDN EnumPrinterData remark section
7548          */
7549
7550         if (!r->in.value_offered && !r->in.data_offered) {
7551                 uint32_t biggest_valuesize = 0;
7552                 uint32_t biggest_datasize = 0;
7553                 int i, name_length;
7554
7555                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7556
7557                 for (i=0; i<count; i++) {
7558
7559                         name_length = strlen(info[i].value_name);
7560                         if (strlen(info[i].value_name) > biggest_valuesize) {
7561                                 biggest_valuesize = name_length;
7562                         }
7563
7564                         if (info[i].data_length > biggest_datasize) {
7565                                 biggest_datasize = info[i].data_length;
7566                         }
7567
7568                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7569                                 biggest_datasize));
7570                 }
7571
7572                 /* the value is an UNICODE string but real_value_size is the length
7573                    in bytes including the trailing 0 */
7574
7575                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7576                 *r->out.data_needed  = biggest_datasize;
7577
7578                 DEBUG(6,("final values: [%d], [%d]\n",
7579                         *r->out.value_needed, *r->out.data_needed));
7580
7581                 return WERR_OK;
7582         }
7583
7584         if (r->in.enum_index < count) {
7585                 val = &info[r->in.enum_index];
7586         }
7587
7588         if (val == NULL) {
7589                 /* out_value should default to "" or else NT4 has
7590                    problems unmarshalling the response */
7591
7592                 if (r->in.value_offered) {
7593                         *r->out.value_needed = 1;
7594                         r->out.value_name = talloc_strdup(r, "");
7595                         if (!r->out.value_name) {
7596                                 return WERR_NOMEM;
7597                         }
7598                 } else {
7599                         r->out.value_name = NULL;
7600                         *r->out.value_needed = 0;
7601                 }
7602
7603                 /* the data is counted in bytes */
7604
7605                 *r->out.data_needed = r->in.data_offered;
7606
7607                 result = WERR_NO_MORE_ITEMS;
7608         } else {
7609                 /*
7610                  * the value is:
7611                  * - counted in bytes in the request
7612                  * - counted in UNICODE chars in the max reply
7613                  * - counted in bytes in the real size
7614                  *
7615                  * take a pause *before* coding not *during* coding
7616                  */
7617
7618                 /* name */
7619                 if (r->in.value_offered) {
7620                         r->out.value_name = talloc_strdup(r, val->value_name);
7621                         if (!r->out.value_name) {
7622                                 return WERR_NOMEM;
7623                         }
7624                         *r->out.value_needed = val->value_name_len;
7625                 } else {
7626                         r->out.value_name = NULL;
7627                         *r->out.value_needed = 0;
7628                 }
7629
7630                 /* type */
7631
7632                 *r->out.type = val->type;
7633
7634                 /* data - counted in bytes */
7635
7636                 /*
7637                  * See the section "Dynamically Typed Query Parameters"
7638                  * in MS-RPRN.
7639                  */
7640
7641                 if (r->out.data && val->data && val->data->data &&
7642                                 val->data_length && r->in.data_offered) {
7643                         memcpy(r->out.data, val->data->data,
7644                                 MIN(val->data_length,r->in.data_offered));
7645                 }
7646
7647                 *r->out.data_needed = val->data_length;
7648
7649                 result = WERR_OK;
7650         }
7651
7652         return result;
7653 }
7654
7655 /****************************************************************
7656  _spoolss_SetPrinterData
7657 ****************************************************************/
7658
7659 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7660                                struct spoolss_SetPrinterData *r)
7661 {
7662         struct spoolss_SetPrinterDataEx r2;
7663
7664         r2.in.handle            = r->in.handle;
7665         r2.in.key_name          = "PrinterDriverData";
7666         r2.in.value_name        = r->in.value_name;
7667         r2.in.type              = r->in.type;
7668         r2.in.data              = r->in.data;
7669         r2.in.offered           = r->in.offered;
7670
7671         return _spoolss_SetPrinterDataEx(p, &r2);
7672 }
7673
7674 /****************************************************************
7675  _spoolss_ResetPrinter
7676 ****************************************************************/
7677
7678 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7679                              struct spoolss_ResetPrinter *r)
7680 {
7681         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7682         int             snum;
7683
7684         DEBUG(5,("_spoolss_ResetPrinter\n"));
7685
7686         /*
7687          * All we do is to check to see if the handle and queue is valid.
7688          * This call really doesn't mean anything to us because we only
7689          * support RAW printing.   --jerry
7690          */
7691
7692         if (!Printer) {
7693                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7694                         OUR_HANDLE(r->in.handle)));
7695                 return WERR_BADFID;
7696         }
7697
7698         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7699                 return WERR_BADFID;
7700
7701
7702         /* blindly return success */
7703         return WERR_OK;
7704 }
7705
7706 /****************************************************************
7707  _spoolss_DeletePrinterData
7708 ****************************************************************/
7709
7710 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7711                                   struct spoolss_DeletePrinterData *r)
7712 {
7713         struct spoolss_DeletePrinterDataEx r2;
7714
7715         r2.in.handle            = r->in.handle;
7716         r2.in.key_name          = "PrinterDriverData";
7717         r2.in.value_name        = r->in.value_name;
7718
7719         return _spoolss_DeletePrinterDataEx(p, &r2);
7720 }
7721
7722 /****************************************************************
7723  _spoolss_AddForm
7724 ****************************************************************/
7725
7726 WERROR _spoolss_AddForm(pipes_struct *p,
7727                         struct spoolss_AddForm *r)
7728 {
7729         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7730         nt_forms_struct tmpForm;
7731         int snum = -1;
7732         WERROR status = WERR_OK;
7733         NT_PRINTER_INFO_LEVEL *printer = NULL;
7734         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7735
7736         int count=0;
7737         nt_forms_struct *list=NULL;
7738         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7739         int i;
7740
7741         DEBUG(5,("_spoolss_AddForm\n"));
7742
7743         if (!Printer) {
7744                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7745                         OUR_HANDLE(r->in.handle)));
7746                 return WERR_BADFID;
7747         }
7748
7749
7750         /* forms can be added on printer or on the print server handle */
7751
7752         if ( Printer->printer_type == SPLHND_PRINTER )
7753         {
7754                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7755                         return WERR_BADFID;
7756
7757                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7758                 if (!W_ERROR_IS_OK(status))
7759                         goto done;
7760         }
7761
7762         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7763            and not a printer admin, then fail */
7764
7765         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7766              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7767              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7768                                           p->server_info->info3->base.domain.string,
7769                                           NULL,
7770                                           p->server_info->ptok,
7771                                           lp_printer_admin(snum))) {
7772                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7773                 status = WERR_ACCESS_DENIED;
7774                 goto done;
7775         }
7776
7777         switch (form->flags) {
7778         case SPOOLSS_FORM_USER:
7779         case SPOOLSS_FORM_BUILTIN:
7780         case SPOOLSS_FORM_PRINTER:
7781                 break;
7782         default:
7783                 status = WERR_INVALID_PARAM;
7784                 goto done;
7785         }
7786
7787         /* can't add if builtin */
7788
7789         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7790                 status = WERR_FILE_EXISTS;
7791                 goto done;
7792         }
7793
7794         count = get_ntforms(&list);
7795
7796         for (i=0; i < count; i++) {
7797                 if (strequal(form->form_name, list[i].name)) {
7798                         status = WERR_FILE_EXISTS;
7799                         goto done;
7800                 }
7801         }
7802
7803         if(!add_a_form(&list, form, &count)) {
7804                 status =  WERR_NOMEM;
7805                 goto done;
7806         }
7807
7808         become_root();
7809         write_ntforms(&list, count);
7810         unbecome_root();
7811
7812         /*
7813          * ChangeID must always be set if this is a printer
7814          */
7815
7816         if ( Printer->printer_type == SPLHND_PRINTER )
7817                 status = mod_a_printer(printer, 2);
7818
7819 done:
7820         if ( printer )
7821                 free_a_printer(&printer, 2);
7822         SAFE_FREE(list);
7823
7824         return status;
7825 }
7826
7827 /****************************************************************
7828  _spoolss_DeleteForm
7829 ****************************************************************/
7830
7831 WERROR _spoolss_DeleteForm(pipes_struct *p,
7832                            struct spoolss_DeleteForm *r)
7833 {
7834         const char *form_name = r->in.form_name;
7835         nt_forms_struct tmpForm;
7836         int count=0;
7837         nt_forms_struct *list=NULL;
7838         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7839         int snum = -1;
7840         WERROR status = WERR_OK;
7841         NT_PRINTER_INFO_LEVEL *printer = NULL;
7842         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7843         bool ret = false;
7844
7845         DEBUG(5,("_spoolss_DeleteForm\n"));
7846
7847         if (!Printer) {
7848                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7849                         OUR_HANDLE(r->in.handle)));
7850                 return WERR_BADFID;
7851         }
7852
7853         /* forms can be deleted on printer of on the print server handle */
7854
7855         if ( Printer->printer_type == SPLHND_PRINTER )
7856         {
7857                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7858                         return WERR_BADFID;
7859
7860                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7861                 if (!W_ERROR_IS_OK(status))
7862                         goto done;
7863         }
7864
7865         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7866              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7867              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7868                                           p->server_info->info3->base.domain.string,
7869                                           NULL,
7870                                           p->server_info->ptok,
7871                                           lp_printer_admin(snum))) {
7872                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7873                 return WERR_ACCESS_DENIED;
7874         }
7875
7876
7877         /* can't delete if builtin */
7878
7879         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7880                 status = WERR_INVALID_PARAM;
7881                 goto done;
7882         }
7883
7884         count = get_ntforms(&list);
7885
7886         become_root();
7887         ret = delete_a_form(&list, form_name, &count, &status);
7888         unbecome_root();
7889         if (ret == false) {
7890                 goto done;
7891         }
7892
7893         /*
7894          * ChangeID must always be set if this is a printer
7895          */
7896
7897         if ( Printer->printer_type == SPLHND_PRINTER )
7898                 status = mod_a_printer(printer, 2);
7899
7900 done:
7901         if ( printer )
7902                 free_a_printer(&printer, 2);
7903         SAFE_FREE(list);
7904
7905         return status;
7906 }
7907
7908 /****************************************************************
7909  _spoolss_SetForm
7910 ****************************************************************/
7911
7912 WERROR _spoolss_SetForm(pipes_struct *p,
7913                         struct spoolss_SetForm *r)
7914 {
7915         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7916         nt_forms_struct tmpForm;
7917         int snum = -1;
7918         WERROR status = WERR_OK;
7919         NT_PRINTER_INFO_LEVEL *printer = NULL;
7920         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7921
7922         int count=0;
7923         nt_forms_struct *list=NULL;
7924         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7925
7926         DEBUG(5,("_spoolss_SetForm\n"));
7927
7928         if (!Printer) {
7929                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7930                         OUR_HANDLE(r->in.handle)));
7931                 return WERR_BADFID;
7932         }
7933
7934         /* forms can be modified on printer of on the print server handle */
7935
7936         if ( Printer->printer_type == SPLHND_PRINTER )
7937         {
7938                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7939                         return WERR_BADFID;
7940
7941                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7942                 if (!W_ERROR_IS_OK(status))
7943                         goto done;
7944         }
7945
7946         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7947            and not a printer admin, then fail */
7948
7949         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7950              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7951              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7952                                           p->server_info->info3->base.domain.string,
7953                                           NULL,
7954                                           p->server_info->ptok,
7955                                           lp_printer_admin(snum))) {
7956                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7957                 status = WERR_ACCESS_DENIED;
7958                 goto done;
7959         }
7960
7961         /* can't set if builtin */
7962         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7963                 status = WERR_INVALID_PARAM;
7964                 goto done;
7965         }
7966
7967         count = get_ntforms(&list);
7968         update_a_form(&list, form, count);
7969         become_root();
7970         write_ntforms(&list, count);
7971         unbecome_root();
7972
7973         /*
7974          * ChangeID must always be set if this is a printer
7975          */
7976
7977         if ( Printer->printer_type == SPLHND_PRINTER )
7978                 status = mod_a_printer(printer, 2);
7979
7980
7981 done:
7982         if ( printer )
7983                 free_a_printer(&printer, 2);
7984         SAFE_FREE(list);
7985
7986         return status;
7987 }
7988
7989 /****************************************************************************
7990  fill_print_processor1
7991 ****************************************************************************/
7992
7993 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7994                                     struct spoolss_PrintProcessorInfo1 *r,
7995                                     const char *print_processor_name)
7996 {
7997         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7998         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7999
8000         return WERR_OK;
8001 }
8002
8003 /****************************************************************************
8004  enumprintprocessors level 1.
8005 ****************************************************************************/
8006
8007 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8008                                           union spoolss_PrintProcessorInfo **info_p,
8009                                           uint32_t *count)
8010 {
8011         union spoolss_PrintProcessorInfo *info;
8012         WERROR result;
8013
8014         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8015         W_ERROR_HAVE_NO_MEMORY(info);
8016
8017         *count = 1;
8018
8019         result = fill_print_processor1(info, &info[0].info1, "winprint");
8020         if (!W_ERROR_IS_OK(result)) {
8021                 goto out;
8022         }
8023
8024  out:
8025         if (!W_ERROR_IS_OK(result)) {
8026                 TALLOC_FREE(info);
8027                 *count = 0;
8028                 return result;
8029         }
8030
8031         *info_p = info;
8032
8033         return WERR_OK;
8034 }
8035
8036 /****************************************************************
8037  _spoolss_EnumPrintProcessors
8038 ****************************************************************/
8039
8040 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8041                                     struct spoolss_EnumPrintProcessors *r)
8042 {
8043         WERROR result;
8044
8045         /* that's an [in out] buffer */
8046
8047         if (!r->in.buffer && (r->in.offered != 0)) {
8048                 return WERR_INVALID_PARAM;
8049         }
8050
8051         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8052
8053         /*
8054          * Enumerate the print processors ...
8055          *
8056          * Just reply with "winprint", to keep NT happy
8057          * and I can use my nice printer checker.
8058          */
8059
8060         *r->out.count = 0;
8061         *r->out.needed = 0;
8062         *r->out.info = NULL;
8063
8064         switch (r->in.level) {
8065         case 1:
8066                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8067                                                      r->out.count);
8068                 break;
8069         default:
8070                 return WERR_UNKNOWN_LEVEL;
8071         }
8072
8073         if (!W_ERROR_IS_OK(result)) {
8074                 return result;
8075         }
8076
8077         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8078                                                      spoolss_EnumPrintProcessors,
8079                                                      *r->out.info, r->in.level,
8080                                                      *r->out.count);
8081         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8082         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8083
8084         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8085 }
8086
8087 /****************************************************************************
8088  fill_printprocdatatype1
8089 ****************************************************************************/
8090
8091 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8092                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8093                                       const char *name_array)
8094 {
8095         r->name_array = talloc_strdup(mem_ctx, name_array);
8096         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8097
8098         return WERR_OK;
8099 }
8100
8101 /****************************************************************************
8102  enumprintprocdatatypes level 1.
8103 ****************************************************************************/
8104
8105 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8106                                              union spoolss_PrintProcDataTypesInfo **info_p,
8107                                              uint32_t *count)
8108 {
8109         WERROR result;
8110         union spoolss_PrintProcDataTypesInfo *info;
8111
8112         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8113         W_ERROR_HAVE_NO_MEMORY(info);
8114
8115         *count = 1;
8116
8117         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8118         if (!W_ERROR_IS_OK(result)) {
8119                 goto out;
8120         }
8121
8122  out:
8123         if (!W_ERROR_IS_OK(result)) {
8124                 TALLOC_FREE(info);
8125                 *count = 0;
8126                 return result;
8127         }
8128
8129         *info_p = info;
8130
8131         return WERR_OK;
8132 }
8133
8134 /****************************************************************
8135  _spoolss_EnumPrintProcDataTypes
8136 ****************************************************************/
8137
8138 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8139                                        struct spoolss_EnumPrintProcDataTypes *r)
8140 {
8141         WERROR result;
8142
8143         /* that's an [in out] buffer */
8144
8145         if (!r->in.buffer && (r->in.offered != 0)) {
8146                 return WERR_INVALID_PARAM;
8147         }
8148
8149         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8150
8151         *r->out.count = 0;
8152         *r->out.needed = 0;
8153         *r->out.info = NULL;
8154
8155         switch (r->in.level) {
8156         case 1:
8157                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8158                                                         r->out.count);
8159                 break;
8160         default:
8161                 return WERR_UNKNOWN_LEVEL;
8162         }
8163
8164         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8165                                                      spoolss_EnumPrintProcDataTypes, 
8166                                                      *r->out.info, r->in.level,
8167                                                      *r->out.count);
8168         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8169         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8170
8171         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8172 }
8173
8174 /****************************************************************************
8175  fill_monitor_1
8176 ****************************************************************************/
8177
8178 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8179                              struct spoolss_MonitorInfo1 *r,
8180                              const char *monitor_name)
8181 {
8182         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8183         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8184
8185         return WERR_OK;
8186 }
8187
8188 /****************************************************************************
8189  fill_monitor_2
8190 ****************************************************************************/
8191
8192 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8193                              struct spoolss_MonitorInfo2 *r,
8194                              const char *monitor_name,
8195                              const char *environment,
8196                              const char *dll_name)
8197 {
8198         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8199         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8200         r->environment                  = talloc_strdup(mem_ctx, environment);
8201         W_ERROR_HAVE_NO_MEMORY(r->environment);
8202         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8203         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8204
8205         return WERR_OK;
8206 }
8207
8208 /****************************************************************************
8209  enumprintmonitors level 1.
8210 ****************************************************************************/
8211
8212 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8213                                         union spoolss_MonitorInfo **info_p,
8214                                         uint32_t *count)
8215 {
8216         union spoolss_MonitorInfo *info;
8217         WERROR result = WERR_OK;
8218
8219         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8220         W_ERROR_HAVE_NO_MEMORY(info);
8221
8222         *count = 2;
8223
8224         result = fill_monitor_1(info, &info[0].info1,
8225                                 SPL_LOCAL_PORT);
8226         if (!W_ERROR_IS_OK(result)) {
8227                 goto out;
8228         }
8229
8230         result = fill_monitor_1(info, &info[1].info1,
8231                                 SPL_TCPIP_PORT);
8232         if (!W_ERROR_IS_OK(result)) {
8233                 goto out;
8234         }
8235
8236 out:
8237         if (!W_ERROR_IS_OK(result)) {
8238                 TALLOC_FREE(info);
8239                 *count = 0;
8240                 return result;
8241         }
8242
8243         *info_p = info;
8244
8245         return WERR_OK;
8246 }
8247
8248 /****************************************************************************
8249  enumprintmonitors level 2.
8250 ****************************************************************************/
8251
8252 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8253                                         union spoolss_MonitorInfo **info_p,
8254                                         uint32_t *count)
8255 {
8256         union spoolss_MonitorInfo *info;
8257         WERROR result = WERR_OK;
8258
8259         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8260         W_ERROR_HAVE_NO_MEMORY(info);
8261
8262         *count = 2;
8263
8264         result = fill_monitor_2(info, &info[0].info2,
8265                                 SPL_LOCAL_PORT,
8266                                 "Windows NT X86", /* FIXME */
8267                                 "localmon.dll");
8268         if (!W_ERROR_IS_OK(result)) {
8269                 goto out;
8270         }
8271
8272         result = fill_monitor_2(info, &info[1].info2,
8273                                 SPL_TCPIP_PORT,
8274                                 "Windows NT X86", /* FIXME */
8275                                 "tcpmon.dll");
8276         if (!W_ERROR_IS_OK(result)) {
8277                 goto out;
8278         }
8279
8280 out:
8281         if (!W_ERROR_IS_OK(result)) {
8282                 TALLOC_FREE(info);
8283                 *count = 0;
8284                 return result;
8285         }
8286
8287         *info_p = info;
8288
8289         return WERR_OK;
8290 }
8291
8292 /****************************************************************
8293  _spoolss_EnumMonitors
8294 ****************************************************************/
8295
8296 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8297                              struct spoolss_EnumMonitors *r)
8298 {
8299         WERROR result;
8300
8301         /* that's an [in out] buffer */
8302
8303         if (!r->in.buffer && (r->in.offered != 0)) {
8304                 return WERR_INVALID_PARAM;
8305         }
8306
8307         DEBUG(5,("_spoolss_EnumMonitors\n"));
8308
8309         /*
8310          * Enumerate the print monitors ...
8311          *
8312          * Just reply with "Local Port", to keep NT happy
8313          * and I can use my nice printer checker.
8314          */
8315
8316         *r->out.count = 0;
8317         *r->out.needed = 0;
8318         *r->out.info = NULL;
8319
8320         switch (r->in.level) {
8321         case 1:
8322                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8323                                                    r->out.count);
8324                 break;
8325         case 2:
8326                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8327                                                    r->out.count);
8328                 break;
8329         default:
8330                 return WERR_UNKNOWN_LEVEL;
8331         }
8332
8333         if (!W_ERROR_IS_OK(result)) {
8334                 return result;
8335         }
8336
8337         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8338                                                      spoolss_EnumMonitors, 
8339                                                      *r->out.info, r->in.level,
8340                                                      *r->out.count);
8341         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8342         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8343
8344         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8345 }
8346
8347 /****************************************************************************
8348 ****************************************************************************/
8349
8350 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8351                              const print_queue_struct *queue,
8352                              int count, int snum,
8353                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8354                              uint32_t jobid,
8355                              struct spoolss_JobInfo1 *r)
8356 {
8357         int i = 0;
8358         bool found = false;
8359
8360         for (i=0; i<count; i++) {
8361                 if (queue[i].job == (int)jobid) {
8362                         found = true;
8363                         break;
8364                 }
8365         }
8366
8367         if (found == false) {
8368                 /* NT treats not found as bad param... yet another bad choice */
8369                 return WERR_INVALID_PARAM;
8370         }
8371
8372         return fill_job_info1(mem_ctx,
8373                               r,
8374                               &queue[i],
8375                               i,
8376                               snum,
8377                               ntprinter);
8378 }
8379
8380 /****************************************************************************
8381 ****************************************************************************/
8382
8383 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8384                              const print_queue_struct *queue,
8385                              int count, int snum,
8386                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8387                              uint32_t jobid,
8388                              struct spoolss_JobInfo2 *r)
8389 {
8390         int i = 0;
8391         bool found = false;
8392         struct spoolss_DeviceMode *devmode;
8393
8394         for (i=0; i<count; i++) {
8395                 if (queue[i].job == (int)jobid) {
8396                         found = true;
8397                         break;
8398                 }
8399         }
8400
8401         if (found == false) {
8402                 /* NT treats not found as bad param... yet another bad
8403                    choice */
8404                 return WERR_INVALID_PARAM;
8405         }
8406
8407         /*
8408          * if the print job does not have a DEVMODE associated with it,
8409          * just use the one for the printer. A NULL devicemode is not
8410          *  a failure condition
8411          */
8412
8413         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8414         if (!devmode) {
8415                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8416                 W_ERROR_HAVE_NO_MEMORY(devmode);
8417         }
8418
8419         return fill_job_info2(mem_ctx,
8420                               r,
8421                               &queue[i],
8422                               i,
8423                               snum,
8424                               ntprinter,
8425                               devmode);
8426 }
8427
8428 /****************************************************************
8429  _spoolss_GetJob
8430 ****************************************************************/
8431
8432 WERROR _spoolss_GetJob(pipes_struct *p,
8433                        struct spoolss_GetJob *r)
8434 {
8435         WERROR result = WERR_OK;
8436         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8437         int snum;
8438         int count;
8439         print_queue_struct      *queue = NULL;
8440         print_status_struct prt_status;
8441
8442         /* that's an [in out] buffer */
8443
8444         if (!r->in.buffer && (r->in.offered != 0)) {
8445                 return WERR_INVALID_PARAM;
8446         }
8447
8448         DEBUG(5,("_spoolss_GetJob\n"));
8449
8450         *r->out.needed = 0;
8451
8452         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8453                 return WERR_BADFID;
8454         }
8455
8456         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8457         if (!W_ERROR_IS_OK(result)) {
8458                 return result;
8459         }
8460
8461         count = print_queue_status(snum, &queue, &prt_status);
8462
8463         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8464                      count, prt_status.status, prt_status.message));
8465
8466         switch (r->in.level) {
8467         case 1:
8468                 result = getjob_level_1(p->mem_ctx,
8469                                         queue, count, snum, ntprinter,
8470                                         r->in.job_id, &r->out.info->info1);
8471                 break;
8472         case 2:
8473                 result = getjob_level_2(p->mem_ctx,
8474                                         queue, count, snum, ntprinter,
8475                                         r->in.job_id, &r->out.info->info2);
8476                 break;
8477         default:
8478                 result = WERR_UNKNOWN_LEVEL;
8479                 break;
8480         }
8481
8482         SAFE_FREE(queue);
8483         free_a_printer(&ntprinter, 2);
8484
8485         if (!W_ERROR_IS_OK(result)) {
8486                 TALLOC_FREE(r->out.info);
8487                 return result;
8488         }
8489
8490         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8491                                                                                    r->in.level);
8492         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8493
8494         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8495 }
8496
8497 /****************************************************************
8498  _spoolss_GetPrinterDataEx
8499 ****************************************************************/
8500
8501 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8502                                  struct spoolss_GetPrinterDataEx *r)
8503 {
8504
8505         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8506         struct regval_blob              *val = NULL;
8507         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8508         int                     snum = 0;
8509         WERROR result = WERR_OK;
8510         DATA_BLOB blob;
8511
8512         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8513
8514         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8515                 r->in.key_name, r->in.value_name));
8516
8517         /* in case of problem, return some default values */
8518
8519         *r->out.needed  = 0;
8520         *r->out.type    = REG_NONE;
8521
8522         if (!Printer) {
8523                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8524                         OUR_HANDLE(r->in.handle)));
8525                 result = WERR_BADFID;
8526                 goto done;
8527         }
8528
8529         /* Is the handle to a printer or to the server? */
8530
8531         if (Printer->printer_type == SPLHND_SERVER) {
8532
8533                 union spoolss_PrinterData data;
8534
8535                 result = getprinterdata_printer_server(p->mem_ctx,
8536                                                        r->in.value_name,
8537                                                        r->out.type,
8538                                                        &data);
8539                 if (!W_ERROR_IS_OK(result)) {
8540                         goto done;
8541                 }
8542
8543                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8544                                                   *r->out.type, &data);
8545                 if (!W_ERROR_IS_OK(result)) {
8546                         goto done;
8547                 }
8548
8549                 *r->out.needed = blob.length;
8550
8551                 if (r->in.offered >= *r->out.needed) {
8552                         memcpy(r->out.data, blob.data, blob.length);
8553                 }
8554
8555                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8556         }
8557
8558         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8559                 result = WERR_BADFID;
8560                 goto done;
8561         }
8562
8563         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8564         if (!W_ERROR_IS_OK(result)) {
8565                 goto done;
8566         }
8567
8568         /* check to see if the keyname is valid */
8569         if (!strlen(r->in.key_name)) {
8570                 result = WERR_INVALID_PARAM;
8571                 goto done;
8572         }
8573
8574         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8575
8576         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8577             strequal(r->in.value_name, "ChangeId")) {
8578                 *r->out.type = REG_DWORD;
8579                 *r->out.needed = 4;
8580                 if (r->in.offered >= *r->out.needed) {
8581                         SIVAL(r->out.data, 0, printer->info_2->changeid);
8582                         result = WERR_OK;
8583                 }
8584                 goto done;
8585         }
8586
8587         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8588                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8589                         "Invalid keyname [%s]\n", r->in.key_name ));
8590                 result = WERR_BADFILE;
8591                 goto done;
8592         }
8593
8594         val = get_printer_data(printer->info_2,
8595                                r->in.key_name, r->in.value_name);
8596         if (!val) {
8597                 result = WERR_BADFILE;
8598                 goto done;
8599         }
8600
8601         *r->out.needed = regval_size(val);
8602         *r->out.type = regval_type(val);
8603
8604         if (r->in.offered >= *r->out.needed) {
8605                 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8606         }
8607  done:
8608         if (printer) {
8609                 free_a_printer(&printer, 2);
8610         }
8611
8612         if (!W_ERROR_IS_OK(result)) {
8613                 return result;
8614         }
8615
8616         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8617         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8618
8619         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8620 }
8621
8622 /****************************************************************
8623  _spoolss_SetPrinterDataEx
8624 ****************************************************************/
8625
8626 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8627                                  struct spoolss_SetPrinterDataEx *r)
8628 {
8629         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8630         int                     snum = 0;
8631         WERROR                  result = WERR_OK;
8632         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8633         char                    *oid_string;
8634
8635         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8636
8637         /* From MSDN documentation of SetPrinterDataEx: pass request to
8638            SetPrinterData if key is "PrinterDriverData" */
8639
8640         if (!Printer) {
8641                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8642                         OUR_HANDLE(r->in.handle)));
8643                 return WERR_BADFID;
8644         }
8645
8646         if (Printer->printer_type == SPLHND_SERVER) {
8647                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8648                         "Not implemented for server handles yet\n"));
8649                 return WERR_INVALID_PARAM;
8650         }
8651
8652         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8653                 return WERR_BADFID;
8654         }
8655
8656         /*
8657          * Access check : NT returns "access denied" if you make a
8658          * SetPrinterData call without the necessary privildge.
8659          * we were originally returning OK if nothing changed
8660          * which made Win2k issue **a lot** of SetPrinterData
8661          * when connecting to a printer  --jerry
8662          */
8663
8664         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8665                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8666                         "change denied by handle access permissions\n"));
8667                 return WERR_ACCESS_DENIED;
8668         }
8669
8670         result = winreg_get_printer(Printer, p->server_info,
8671                                     Printer->servername,
8672                                     lp_servicename(snum),
8673                                     &pinfo2);
8674         if (!W_ERROR_IS_OK(result)) {
8675                 return result;
8676         }
8677
8678         /* check for OID in valuename */
8679
8680         oid_string = strchr(r->in.value_name, ',');
8681         if (oid_string) {
8682                 *oid_string = '\0';
8683                 oid_string++;
8684         }
8685
8686         /* save the registry data */
8687
8688         result = winreg_set_printer_dataex(p->mem_ctx,
8689                                            p->server_info,
8690                                            pinfo2->sharename,
8691                                            r->in.key_name,
8692                                            r->in.value_name,
8693                                            r->in.type,
8694                                            r->in.data,
8695                                            r->in.offered);
8696
8697         if (W_ERROR_IS_OK(result)) {
8698                 /* save the OID if one was specified */
8699                 if (oid_string) {
8700                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8701                                 r->in.key_name, SPOOL_OID_KEY);
8702                         if (!str) {
8703                                 result = WERR_NOMEM;
8704                                 goto done;
8705                         }
8706
8707                         /*
8708                          * I'm not checking the status here on purpose.  Don't know
8709                          * if this is right, but I'm returning the status from the
8710                          * previous set_printer_dataex() call.  I have no idea if
8711                          * this is right.    --jerry
8712                          */
8713                         winreg_set_printer_dataex(p->mem_ctx,
8714                                                   p->server_info,
8715                                                   pinfo2->sharename,
8716                                                   str,
8717                                                   r->in.value_name,
8718                                                   REG_SZ,
8719                                                   (uint8_t *) oid_string,
8720                                                   strlen(oid_string) + 1);
8721                 }
8722
8723                 result = winreg_printer_update_changeid(p->mem_ctx,
8724                                                         p->server_info,
8725                                                         lp_const_servicename(snum));
8726
8727         }
8728
8729 done:
8730         talloc_free(pinfo2);
8731         return result;
8732 }
8733
8734 /****************************************************************
8735  _spoolss_DeletePrinterDataEx
8736 ****************************************************************/
8737
8738 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8739                                     struct spoolss_DeletePrinterDataEx *r)
8740 {
8741         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8742         int             snum=0;
8743         WERROR          status = WERR_OK;
8744         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8745
8746         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8747
8748         if (!Printer) {
8749                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8750                         "Invalid handle (%s:%u:%u).\n",
8751                         OUR_HANDLE(r->in.handle)));
8752                 return WERR_BADFID;
8753         }
8754
8755         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8756                 return WERR_BADFID;
8757
8758         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8759                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8760                         "printer properties change denied by handle\n"));
8761                 return WERR_ACCESS_DENIED;
8762         }
8763
8764         if (!r->in.value_name || !r->in.key_name) {
8765                 return WERR_NOMEM;
8766         }
8767
8768         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8769         if (!W_ERROR_IS_OK(status))
8770                 return status;
8771
8772         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8773
8774         if ( W_ERROR_IS_OK(status) )
8775                 mod_a_printer( printer, 2 );
8776
8777         free_a_printer(&printer, 2);
8778
8779         return status;
8780 }
8781
8782 /****************************************************************
8783  _spoolss_EnumPrinterKey
8784 ****************************************************************/
8785
8786 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8787                                struct spoolss_EnumPrinterKey *r)
8788 {
8789         fstring         *keynames = NULL;
8790         int             num_keys;
8791         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8792         NT_PRINTER_DATA *data;
8793         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8794         int             snum = 0;
8795         WERROR          result = WERR_BADFILE;
8796         int i;
8797         const char **array = NULL;
8798         DATA_BLOB blob;
8799
8800         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8801
8802         if (!Printer) {
8803                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8804                         OUR_HANDLE(r->in.handle)));
8805                 return WERR_BADFID;
8806         }
8807
8808         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8809                 return WERR_BADFID;
8810         }
8811
8812         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8813         if (!W_ERROR_IS_OK(result)) {
8814                 return result;
8815         }
8816
8817         /* get the list of subkey names */
8818
8819         data = printer->info_2->data;
8820
8821         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8822         if (num_keys == -1) {
8823                 result = WERR_BADFILE;
8824                 goto done;
8825         }
8826
8827         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8828         if (!array) {
8829                 result = WERR_NOMEM;
8830                 goto done;
8831         }
8832
8833         if (!num_keys) {
8834                 array[0] = talloc_strdup(array, "");
8835                 if (!array[0]) {
8836                         result = WERR_NOMEM;
8837                         goto done;
8838                 }
8839         }
8840
8841         for (i=0; i < num_keys; i++) {
8842
8843                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8844                         keynames[i]));
8845
8846                 array[i] = talloc_strdup(array, keynames[i]);
8847                 if (!array[i]) {
8848                         result = WERR_NOMEM;
8849                         goto done;
8850                 }
8851         }
8852
8853         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8854                 result = WERR_NOMEM;
8855                 goto done;
8856         }
8857
8858         *r->out._ndr_size = r->in.offered / 2;
8859         *r->out.needed = blob.length;
8860
8861         if (r->in.offered < *r->out.needed) {
8862                 result = WERR_MORE_DATA;
8863         } else {
8864                 result = WERR_OK;
8865                 r->out.key_buffer->string_array = array;
8866         }
8867
8868  done:
8869         if (!W_ERROR_IS_OK(result)) {
8870                 TALLOC_FREE(array);
8871                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8872                         *r->out.needed = 0;
8873                 }
8874         }
8875
8876         free_a_printer(&printer, 2);
8877         SAFE_FREE(keynames);
8878
8879         return result;
8880 }
8881
8882 /****************************************************************
8883  _spoolss_DeletePrinterKey
8884 ****************************************************************/
8885
8886 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8887                                  struct spoolss_DeletePrinterKey *r)
8888 {
8889         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8890         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8891         int                     snum=0;
8892         WERROR                  status;
8893
8894         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8895
8896         if (!Printer) {
8897                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8898                         OUR_HANDLE(r->in.handle)));
8899                 return WERR_BADFID;
8900         }
8901
8902         /* if keyname == NULL, return error */
8903
8904         if ( !r->in.key_name )
8905                 return WERR_INVALID_PARAM;
8906
8907         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8908                 return WERR_BADFID;
8909
8910         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8911                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8912                         "printer properties change denied by handle\n"));
8913                 return WERR_ACCESS_DENIED;
8914         }
8915
8916         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8917         if (!W_ERROR_IS_OK(status))
8918                 return status;
8919
8920         /* delete the key and all subneys */
8921
8922         status = delete_all_printer_data( printer->info_2, r->in.key_name );
8923
8924         if ( W_ERROR_IS_OK(status) )
8925                 status = mod_a_printer(printer, 2);
8926
8927         free_a_printer( &printer, 2 );
8928
8929         return status;
8930 }
8931
8932 /****************************************************************
8933 ****************************************************************/
8934
8935 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8936                                                    struct regval_blob *v,
8937                                                    struct spoolss_PrinterEnumValues *r)
8938 {
8939         r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
8940         W_ERROR_HAVE_NO_MEMORY(r->data);
8941
8942         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
8943         W_ERROR_HAVE_NO_MEMORY(r->value_name);
8944
8945         r->value_name_len = strlen_m_term(regval_name(v)) * 2;
8946
8947         r->type         = regval_type(v);
8948         r->data_length  = regval_size(v);
8949
8950         if (r->data_length) {
8951                 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
8952         }
8953
8954         return WERR_OK;
8955 }
8956
8957 /****************************************************************
8958  _spoolss_EnumPrinterDataEx
8959 ****************************************************************/
8960
8961 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8962                                   struct spoolss_EnumPrinterDataEx *r)
8963 {
8964         uint32_t        count = 0;
8965         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8966         struct spoolss_PrinterEnumValues *info = NULL;
8967         NT_PRINTER_DATA         *p_data;
8968         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8969         int             snum;
8970         WERROR          result;
8971         int             key_index;
8972         int             i;
8973
8974         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8975
8976         *r->out.count = 0;
8977         *r->out.needed = 0;
8978         *r->out.info = NULL;
8979
8980         if (!Printer) {
8981                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8982                         OUR_HANDLE(r->in.handle)));
8983                 return WERR_BADFID;
8984         }
8985
8986         /*
8987          * first check for a keyname of NULL or "".  Win2k seems to send
8988          * this a lot and we should send back WERR_INVALID_PARAM
8989          * no need to spend time looking up the printer in this case.
8990          * --jerry
8991          */
8992
8993         if (!strlen(r->in.key_name)) {
8994                 result = WERR_INVALID_PARAM;
8995                 goto done;
8996         }
8997
8998         /* get the printer off of disk */
8999
9000         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9001                 return WERR_BADFID;
9002         }
9003
9004         ZERO_STRUCT(printer);
9005         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9006         if (!W_ERROR_IS_OK(result)) {
9007                 return result;
9008         }
9009
9010         /* now look for a match on the key name */
9011
9012         p_data = printer->info_2->data;
9013
9014         key_index = lookup_printerkey(p_data, r->in.key_name);
9015         if (key_index == -1) {
9016                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9017                         r->in.key_name));
9018                 result = WERR_INVALID_PARAM;
9019                 goto done;
9020         }
9021
9022         /* allocate the memory for the array of pointers -- if necessary */
9023
9024         count = regval_ctr_numvals(p_data->keys[key_index].values);
9025         if (!count) {
9026                 result = WERR_OK; /* ??? */
9027                 goto done;
9028         }
9029
9030         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9031                                  struct spoolss_PrinterEnumValues,
9032                                  count);
9033         if (!info) {
9034                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9035                 result = WERR_NOMEM;
9036                 goto done;
9037         }
9038
9039         /*
9040          * loop through all params and build the array to pass
9041          * back to the  client
9042          */
9043
9044         for (i=0; i < count; i++) {
9045
9046                 struct regval_blob      *val;
9047
9048                 /* lookup the registry value */
9049
9050                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9051
9052                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9053
9054                 /* copy the data */
9055
9056                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9057                 if (!W_ERROR_IS_OK(result)) {
9058                         goto done;
9059                 }
9060         }
9061
9062 #if 0 /* FIXME - gd */
9063         /* housekeeping information in the reply */
9064
9065         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9066          * the hand marshalled container size is a multiple
9067          * of 4 bytes for RPC alignment.
9068          */
9069
9070         if (needed % 4) {
9071                 needed += 4-(needed % 4);
9072         }
9073 #endif
9074         *r->out.count   = count;
9075         *r->out.info    = info;
9076
9077  done:
9078
9079         if (printer) {
9080                 free_a_printer(&printer, 2);
9081         }
9082
9083         if (!W_ERROR_IS_OK(result)) {
9084                 return result;
9085         }
9086
9087         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9088                                                spoolss_EnumPrinterDataEx, 
9089                                                *r->out.info,
9090                                                *r->out.count);
9091         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9092         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9093
9094         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9095 }
9096
9097 /****************************************************************************
9098 ****************************************************************************/
9099
9100 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9101                                                  const char *servername,
9102                                                  const char *environment,
9103                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9104 {
9105         WERROR werr;
9106         char *path = NULL;
9107
9108         werr = compose_spoolss_server_path(mem_ctx,
9109                                            servername,
9110                                            environment,
9111                                            SPOOLSS_PRTPROCS_PATH,
9112                                            &path);
9113         if (!W_ERROR_IS_OK(werr)) {
9114                 return werr;
9115         }
9116
9117         DEBUG(4,("print processor directory: [%s]\n", path));
9118
9119         r->directory_name = path;
9120
9121         return WERR_OK;
9122 }
9123
9124 /****************************************************************
9125  _spoolss_GetPrintProcessorDirectory
9126 ****************************************************************/
9127
9128 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9129                                            struct spoolss_GetPrintProcessorDirectory *r)
9130 {
9131         WERROR result;
9132
9133         /* that's an [in out] buffer */
9134
9135         if (!r->in.buffer && (r->in.offered != 0)) {
9136                 return WERR_INVALID_PARAM;
9137         }
9138
9139         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9140                 r->in.level));
9141
9142         *r->out.needed = 0;
9143
9144         /* r->in.level is ignored */
9145
9146         /* We always should reply with a local print processor directory so that
9147          * users are not forced to have a [prnproc$] share on the Samba spoolss
9148          * server - Guenther */
9149
9150         result = getprintprocessordirectory_level_1(p->mem_ctx,
9151                                                     NULL, /* r->in.server */
9152                                                     r->in.environment,
9153                                                     &r->out.info->info1);
9154         if (!W_ERROR_IS_OK(result)) {
9155                 TALLOC_FREE(r->out.info);
9156                 return result;
9157         }
9158
9159         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9160                                                                                    r->out.info, r->in.level);
9161         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9162
9163         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9164 }
9165
9166 /*******************************************************************
9167  ********************************************************************/
9168
9169 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9170                                const char *dllname)
9171 {
9172         enum ndr_err_code ndr_err;
9173         struct spoolss_MonitorUi ui;
9174
9175         ui.dll_name = dllname;
9176
9177         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9178                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9179         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9180                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9181         }
9182         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9183 }
9184
9185 /*******************************************************************
9186  Streams the monitor UI DLL name in UNICODE
9187 *******************************************************************/
9188
9189 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9190                                NT_USER_TOKEN *token, DATA_BLOB *in,
9191                                DATA_BLOB *out, uint32_t *needed)
9192 {
9193         const char *dllname = "tcpmonui.dll";
9194
9195         *needed = (strlen(dllname)+1) * 2;
9196
9197         if (out->length < *needed) {
9198                 return WERR_INSUFFICIENT_BUFFER;
9199         }
9200
9201         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9202                 return WERR_NOMEM;
9203         }
9204
9205         return WERR_OK;
9206 }
9207
9208 /*******************************************************************
9209  ********************************************************************/
9210
9211 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9212                              struct spoolss_PortData1 *port1,
9213                              const DATA_BLOB *buf)
9214 {
9215         enum ndr_err_code ndr_err;
9216         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9217                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9218         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9219                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9220         }
9221         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9222 }
9223
9224 /*******************************************************************
9225  ********************************************************************/
9226
9227 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9228                              struct spoolss_PortData2 *port2,
9229                              const DATA_BLOB *buf)
9230 {
9231         enum ndr_err_code ndr_err;
9232         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9233                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9234         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9235                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9236         }
9237         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9238 }
9239
9240 /*******************************************************************
9241  Create a new TCP/IP port
9242 *******************************************************************/
9243
9244 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9245                              NT_USER_TOKEN *token, DATA_BLOB *in,
9246                              DATA_BLOB *out, uint32_t *needed)
9247 {
9248         struct spoolss_PortData1 port1;
9249         struct spoolss_PortData2 port2;
9250         char *device_uri = NULL;
9251         uint32_t version;
9252
9253         const char *portname;
9254         const char *hostaddress;
9255         const char *queue;
9256         uint32_t port_number;
9257         uint32_t protocol;
9258
9259         /* peek for spoolss_PortData version */
9260
9261         if (!in || (in->length < (128 + 4))) {
9262                 return WERR_GENERAL_FAILURE;
9263         }
9264
9265         version = IVAL(in->data, 128);
9266
9267         switch (version) {
9268                 case 1:
9269                         ZERO_STRUCT(port1);
9270
9271                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9272                                 return WERR_NOMEM;
9273                         }
9274
9275                         portname        = port1.portname;
9276                         hostaddress     = port1.hostaddress;
9277                         queue           = port1.queue;
9278                         protocol        = port1.protocol;
9279                         port_number     = port1.port_number;
9280
9281                         break;
9282                 case 2:
9283                         ZERO_STRUCT(port2);
9284
9285                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9286                                 return WERR_NOMEM;
9287                         }
9288
9289                         portname        = port2.portname;
9290                         hostaddress     = port2.hostaddress;
9291                         queue           = port2.queue;
9292                         protocol        = port2.protocol;
9293                         port_number     = port2.port_number;
9294
9295                         break;
9296                 default:
9297                         DEBUG(1,("xcvtcp_addport: "
9298                                 "unknown version of port_data: %d\n", version));
9299                         return WERR_UNKNOWN_PORT;
9300         }
9301
9302         /* create the device URI and call the add_port_hook() */
9303
9304         switch (protocol) {
9305         case PROTOCOL_RAWTCP_TYPE:
9306                 device_uri = talloc_asprintf(mem_ctx,
9307                                 "socket://%s:%d/", hostaddress,
9308                                 port_number);
9309                 break;
9310
9311         case PROTOCOL_LPR_TYPE:
9312                 device_uri = talloc_asprintf(mem_ctx,
9313                         "lpr://%s/%s", hostaddress, queue );
9314                 break;
9315
9316         default:
9317                 return WERR_UNKNOWN_PORT;
9318         }
9319
9320         if (!device_uri) {
9321                 return WERR_NOMEM;
9322         }
9323
9324         return add_port_hook(mem_ctx, token, portname, device_uri);
9325 }
9326
9327 /*******************************************************************
9328 *******************************************************************/
9329
9330 struct xcv_api_table xcvtcp_cmds[] = {
9331         { "MonitorUI",  xcvtcp_monitorui },
9332         { "AddPort",    xcvtcp_addport},
9333         { NULL,         NULL }
9334 };
9335
9336 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9337                                      NT_USER_TOKEN *token, const char *command,
9338                                      DATA_BLOB *inbuf,
9339                                      DATA_BLOB *outbuf,
9340                                      uint32_t *needed )
9341 {
9342         int i;
9343
9344         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9345
9346         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9347                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9348                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9349         }
9350
9351         return WERR_BADFUNC;
9352 }
9353
9354 /*******************************************************************
9355 *******************************************************************/
9356 #if 0   /* don't support management using the "Local Port" monitor */
9357
9358 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9359                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9360                                  DATA_BLOB *out, uint32_t *needed)
9361 {
9362         const char *dllname = "localui.dll";
9363
9364         *needed = (strlen(dllname)+1) * 2;
9365
9366         if (out->length < *needed) {
9367                 return WERR_INSUFFICIENT_BUFFER;
9368         }
9369
9370         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9371                 return WERR_NOMEM;
9372         }
9373
9374         return WERR_OK;
9375 }
9376
9377 /*******************************************************************
9378 *******************************************************************/
9379
9380 struct xcv_api_table xcvlocal_cmds[] = {
9381         { "MonitorUI",  xcvlocal_monitorui },
9382         { NULL,         NULL }
9383 };
9384 #else
9385 struct xcv_api_table xcvlocal_cmds[] = {
9386         { NULL,         NULL }
9387 };
9388 #endif
9389
9390
9391
9392 /*******************************************************************
9393 *******************************************************************/
9394
9395 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9396                                        NT_USER_TOKEN *token, const char *command,
9397                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9398                                        uint32_t *needed)
9399 {
9400         int i;
9401
9402         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9403
9404         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9405                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9406                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9407         }
9408         return WERR_BADFUNC;
9409 }
9410
9411 /****************************************************************
9412  _spoolss_XcvData
9413 ****************************************************************/
9414
9415 WERROR _spoolss_XcvData(pipes_struct *p,
9416                         struct spoolss_XcvData *r)
9417 {
9418         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9419         DATA_BLOB out_data = data_blob_null;
9420         WERROR werror;
9421
9422         if (!Printer) {
9423                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9424                         OUR_HANDLE(r->in.handle)));
9425                 return WERR_BADFID;
9426         }
9427
9428         /* Has to be a handle to the TCP/IP port monitor */
9429
9430         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9431                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9432                 return WERR_BADFID;
9433         }
9434
9435         /* requires administrative access to the server */
9436
9437         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9438                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9439                 return WERR_ACCESS_DENIED;
9440         }
9441
9442         /* Allocate the outgoing buffer */
9443
9444         if (r->in.out_data_size) {
9445                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9446                 if (out_data.data == NULL) {
9447                         return WERR_NOMEM;
9448                 }
9449         }
9450
9451         switch ( Printer->printer_type ) {
9452         case SPLHND_PORTMON_TCP:
9453                 werror = process_xcvtcp_command(p->mem_ctx,
9454                                                 p->server_info->ptok,
9455                                                 r->in.function_name,
9456                                                 &r->in.in_data, &out_data,
9457                                                 r->out.needed);
9458                 break;
9459         case SPLHND_PORTMON_LOCAL:
9460                 werror = process_xcvlocal_command(p->mem_ctx,
9461                                                   p->server_info->ptok,
9462                                                   r->in.function_name,
9463                                                   &r->in.in_data, &out_data,
9464                                                   r->out.needed);
9465                 break;
9466         default:
9467                 werror = WERR_INVALID_PRINT_MONITOR;
9468         }
9469
9470         if (!W_ERROR_IS_OK(werror)) {
9471                 return werror;
9472         }
9473
9474         *r->out.status_code = 0;
9475
9476         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9477                 memcpy(r->out.out_data, out_data.data,
9478                         MIN(r->in.out_data_size, out_data.length));
9479         }
9480
9481         return WERR_OK;
9482 }
9483
9484 /****************************************************************
9485  _spoolss_AddPrintProcessor
9486 ****************************************************************/
9487
9488 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9489                                   struct spoolss_AddPrintProcessor *r)
9490 {
9491         /* for now, just indicate success and ignore the add.  We'll
9492            automatically set the winprint processor for printer
9493            entries later.  Used to debug the LexMark Optra S 1855 PCL
9494            driver --jerry */
9495
9496         return WERR_OK;
9497 }
9498
9499 /****************************************************************
9500  _spoolss_AddPort
9501 ****************************************************************/
9502
9503 WERROR _spoolss_AddPort(pipes_struct *p,
9504                         struct spoolss_AddPort *r)
9505 {
9506         /* do what w2k3 does */
9507
9508         return WERR_NOT_SUPPORTED;
9509 }
9510
9511 /****************************************************************
9512  _spoolss_GetPrinterDriver
9513 ****************************************************************/
9514
9515 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9516                                  struct spoolss_GetPrinterDriver *r)
9517 {
9518         p->rng_fault_state = true;
9519         return WERR_NOT_SUPPORTED;
9520 }
9521
9522 /****************************************************************
9523  _spoolss_ReadPrinter
9524 ****************************************************************/
9525
9526 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9527                             struct spoolss_ReadPrinter *r)
9528 {
9529         p->rng_fault_state = true;
9530         return WERR_NOT_SUPPORTED;
9531 }
9532
9533 /****************************************************************
9534  _spoolss_WaitForPrinterChange
9535 ****************************************************************/
9536
9537 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9538                                      struct spoolss_WaitForPrinterChange *r)
9539 {
9540         p->rng_fault_state = true;
9541         return WERR_NOT_SUPPORTED;
9542 }
9543
9544 /****************************************************************
9545  _spoolss_ConfigurePort
9546 ****************************************************************/
9547
9548 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9549                               struct spoolss_ConfigurePort *r)
9550 {
9551         p->rng_fault_state = true;
9552         return WERR_NOT_SUPPORTED;
9553 }
9554
9555 /****************************************************************
9556  _spoolss_DeletePort
9557 ****************************************************************/
9558
9559 WERROR _spoolss_DeletePort(pipes_struct *p,
9560                            struct spoolss_DeletePort *r)
9561 {
9562         p->rng_fault_state = true;
9563         return WERR_NOT_SUPPORTED;
9564 }
9565
9566 /****************************************************************
9567  _spoolss_CreatePrinterIC
9568 ****************************************************************/
9569
9570 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9571                                 struct spoolss_CreatePrinterIC *r)
9572 {
9573         p->rng_fault_state = true;
9574         return WERR_NOT_SUPPORTED;
9575 }
9576
9577 /****************************************************************
9578  _spoolss_PlayGDIScriptOnPrinterIC
9579 ****************************************************************/
9580
9581 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9582                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9583 {
9584         p->rng_fault_state = true;
9585         return WERR_NOT_SUPPORTED;
9586 }
9587
9588 /****************************************************************
9589  _spoolss_DeletePrinterIC
9590 ****************************************************************/
9591
9592 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9593                                 struct spoolss_DeletePrinterIC *r)
9594 {
9595         p->rng_fault_state = true;
9596         return WERR_NOT_SUPPORTED;
9597 }
9598
9599 /****************************************************************
9600  _spoolss_AddPrinterConnection
9601 ****************************************************************/
9602
9603 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9604                                      struct spoolss_AddPrinterConnection *r)
9605 {
9606         p->rng_fault_state = true;
9607         return WERR_NOT_SUPPORTED;
9608 }
9609
9610 /****************************************************************
9611  _spoolss_DeletePrinterConnection
9612 ****************************************************************/
9613
9614 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9615                                         struct spoolss_DeletePrinterConnection *r)
9616 {
9617         p->rng_fault_state = true;
9618         return WERR_NOT_SUPPORTED;
9619 }
9620
9621 /****************************************************************
9622  _spoolss_PrinterMessageBox
9623 ****************************************************************/
9624
9625 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9626                                   struct spoolss_PrinterMessageBox *r)
9627 {
9628         p->rng_fault_state = true;
9629         return WERR_NOT_SUPPORTED;
9630 }
9631
9632 /****************************************************************
9633  _spoolss_AddMonitor
9634 ****************************************************************/
9635
9636 WERROR _spoolss_AddMonitor(pipes_struct *p,
9637                            struct spoolss_AddMonitor *r)
9638 {
9639         p->rng_fault_state = true;
9640         return WERR_NOT_SUPPORTED;
9641 }
9642
9643 /****************************************************************
9644  _spoolss_DeleteMonitor
9645 ****************************************************************/
9646
9647 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9648                               struct spoolss_DeleteMonitor *r)
9649 {
9650         p->rng_fault_state = true;
9651         return WERR_NOT_SUPPORTED;
9652 }
9653
9654 /****************************************************************
9655  _spoolss_DeletePrintProcessor
9656 ****************************************************************/
9657
9658 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9659                                      struct spoolss_DeletePrintProcessor *r)
9660 {
9661         p->rng_fault_state = true;
9662         return WERR_NOT_SUPPORTED;
9663 }
9664
9665 /****************************************************************
9666  _spoolss_AddPrintProvidor
9667 ****************************************************************/
9668
9669 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9670                                  struct spoolss_AddPrintProvidor *r)
9671 {
9672         p->rng_fault_state = true;
9673         return WERR_NOT_SUPPORTED;
9674 }
9675
9676 /****************************************************************
9677  _spoolss_DeletePrintProvidor
9678 ****************************************************************/
9679
9680 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9681                                     struct spoolss_DeletePrintProvidor *r)
9682 {
9683         p->rng_fault_state = true;
9684         return WERR_NOT_SUPPORTED;
9685 }
9686
9687 /****************************************************************
9688  _spoolss_FindFirstPrinterChangeNotification
9689 ****************************************************************/
9690
9691 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9692                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9693 {
9694         p->rng_fault_state = true;
9695         return WERR_NOT_SUPPORTED;
9696 }
9697
9698 /****************************************************************
9699  _spoolss_FindNextPrinterChangeNotification
9700 ****************************************************************/
9701
9702 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9703                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9704 {
9705         p->rng_fault_state = true;
9706         return WERR_NOT_SUPPORTED;
9707 }
9708
9709 /****************************************************************
9710  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9711 ****************************************************************/
9712
9713 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9714                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9715 {
9716         p->rng_fault_state = true;
9717         return WERR_NOT_SUPPORTED;
9718 }
9719
9720 /****************************************************************
9721  _spoolss_ReplyOpenPrinter
9722 ****************************************************************/
9723
9724 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9725                                  struct spoolss_ReplyOpenPrinter *r)
9726 {
9727         p->rng_fault_state = true;
9728         return WERR_NOT_SUPPORTED;
9729 }
9730
9731 /****************************************************************
9732  _spoolss_RouterReplyPrinter
9733 ****************************************************************/
9734
9735 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9736                                    struct spoolss_RouterReplyPrinter *r)
9737 {
9738         p->rng_fault_state = true;
9739         return WERR_NOT_SUPPORTED;
9740 }
9741
9742 /****************************************************************
9743  _spoolss_ReplyClosePrinter
9744 ****************************************************************/
9745
9746 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9747                                   struct spoolss_ReplyClosePrinter *r)
9748 {
9749         p->rng_fault_state = true;
9750         return WERR_NOT_SUPPORTED;
9751 }
9752
9753 /****************************************************************
9754  _spoolss_AddPortEx
9755 ****************************************************************/
9756
9757 WERROR _spoolss_AddPortEx(pipes_struct *p,
9758                           struct spoolss_AddPortEx *r)
9759 {
9760         p->rng_fault_state = true;
9761         return WERR_NOT_SUPPORTED;
9762 }
9763
9764 /****************************************************************
9765  _spoolss_RouterFindFirstPrinterChangeNotification
9766 ****************************************************************/
9767
9768 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9769                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9770 {
9771         p->rng_fault_state = true;
9772         return WERR_NOT_SUPPORTED;
9773 }
9774
9775 /****************************************************************
9776  _spoolss_SpoolerInit
9777 ****************************************************************/
9778
9779 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9780                             struct spoolss_SpoolerInit *r)
9781 {
9782         p->rng_fault_state = true;
9783         return WERR_NOT_SUPPORTED;
9784 }
9785
9786 /****************************************************************
9787  _spoolss_ResetPrinterEx
9788 ****************************************************************/
9789
9790 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9791                                struct spoolss_ResetPrinterEx *r)
9792 {
9793         p->rng_fault_state = true;
9794         return WERR_NOT_SUPPORTED;
9795 }
9796
9797 /****************************************************************
9798  _spoolss_RouterReplyPrinterEx
9799 ****************************************************************/
9800
9801 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9802                                      struct spoolss_RouterReplyPrinterEx *r)
9803 {
9804         p->rng_fault_state = true;
9805         return WERR_NOT_SUPPORTED;
9806 }
9807
9808 /****************************************************************
9809  _spoolss_44
9810 ****************************************************************/
9811
9812 WERROR _spoolss_44(pipes_struct *p,
9813                    struct spoolss_44 *r)
9814 {
9815         p->rng_fault_state = true;
9816         return WERR_NOT_SUPPORTED;
9817 }
9818
9819 /****************************************************************
9820  _spoolss_47
9821 ****************************************************************/
9822
9823 WERROR _spoolss_47(pipes_struct *p,
9824                    struct spoolss_47 *r)
9825 {
9826         p->rng_fault_state = true;
9827         return WERR_NOT_SUPPORTED;
9828 }
9829
9830 /****************************************************************
9831  _spoolss_4a
9832 ****************************************************************/
9833
9834 WERROR _spoolss_4a(pipes_struct *p,
9835                    struct spoolss_4a *r)
9836 {
9837         p->rng_fault_state = true;
9838         return WERR_NOT_SUPPORTED;
9839 }
9840
9841 /****************************************************************
9842  _spoolss_4b
9843 ****************************************************************/
9844
9845 WERROR _spoolss_4b(pipes_struct *p,
9846                    struct spoolss_4b *r)
9847 {
9848         p->rng_fault_state = true;
9849         return WERR_NOT_SUPPORTED;
9850 }
9851
9852 /****************************************************************
9853  _spoolss_4c
9854 ****************************************************************/
9855
9856 WERROR _spoolss_4c(pipes_struct *p,
9857                    struct spoolss_4c *r)
9858 {
9859         p->rng_fault_state = true;
9860         return WERR_NOT_SUPPORTED;
9861 }
9862
9863 /****************************************************************
9864  _spoolss_53
9865 ****************************************************************/
9866
9867 WERROR _spoolss_53(pipes_struct *p,
9868                    struct spoolss_53 *r)
9869 {
9870         p->rng_fault_state = true;
9871         return WERR_NOT_SUPPORTED;
9872 }
9873
9874 /****************************************************************
9875  _spoolss_55
9876 ****************************************************************/
9877
9878 WERROR _spoolss_55(pipes_struct *p,
9879                    struct spoolss_55 *r)
9880 {
9881         p->rng_fault_state = true;
9882         return WERR_NOT_SUPPORTED;
9883 }
9884
9885 /****************************************************************
9886  _spoolss_56
9887 ****************************************************************/
9888
9889 WERROR _spoolss_56(pipes_struct *p,
9890                    struct spoolss_56 *r)
9891 {
9892         p->rng_fault_state = true;
9893         return WERR_NOT_SUPPORTED;
9894 }
9895
9896 /****************************************************************
9897  _spoolss_57
9898 ****************************************************************/
9899
9900 WERROR _spoolss_57(pipes_struct *p,
9901                    struct spoolss_57 *r)
9902 {
9903         p->rng_fault_state = true;
9904         return WERR_NOT_SUPPORTED;
9905 }
9906
9907 /****************************************************************
9908  _spoolss_5a
9909 ****************************************************************/
9910
9911 WERROR _spoolss_5a(pipes_struct *p,
9912                    struct spoolss_5a *r)
9913 {
9914         p->rng_fault_state = true;
9915         return WERR_NOT_SUPPORTED;
9916 }
9917
9918 /****************************************************************
9919  _spoolss_5b
9920 ****************************************************************/
9921
9922 WERROR _spoolss_5b(pipes_struct *p,
9923                    struct spoolss_5b *r)
9924 {
9925         p->rng_fault_state = true;
9926         return WERR_NOT_SUPPORTED;
9927 }
9928
9929 /****************************************************************
9930  _spoolss_5c
9931 ****************************************************************/
9932
9933 WERROR _spoolss_5c(pipes_struct *p,
9934                    struct spoolss_5c *r)
9935 {
9936         p->rng_fault_state = true;
9937         return WERR_NOT_SUPPORTED;
9938 }
9939
9940 /****************************************************************
9941  _spoolss_5d
9942 ****************************************************************/
9943
9944 WERROR _spoolss_5d(pipes_struct *p,
9945                    struct spoolss_5d *r)
9946 {
9947         p->rng_fault_state = true;
9948         return WERR_NOT_SUPPORTED;
9949 }
9950
9951 /****************************************************************
9952  _spoolss_5e
9953 ****************************************************************/
9954
9955 WERROR _spoolss_5e(pipes_struct *p,
9956                    struct spoolss_5e *r)
9957 {
9958         p->rng_fault_state = true;
9959         return WERR_NOT_SUPPORTED;
9960 }
9961
9962 /****************************************************************
9963  _spoolss_5f
9964 ****************************************************************/
9965
9966 WERROR _spoolss_5f(pipes_struct *p,
9967                    struct spoolss_5f *r)
9968 {
9969         p->rng_fault_state = true;
9970         return WERR_NOT_SUPPORTED;
9971 }
9972
9973 /****************************************************************
9974  _spoolss_60
9975 ****************************************************************/
9976
9977 WERROR _spoolss_60(pipes_struct *p,
9978                    struct spoolss_60 *r)
9979 {
9980         p->rng_fault_state = true;
9981         return WERR_NOT_SUPPORTED;
9982 }
9983
9984 /****************************************************************
9985  _spoolss_61
9986 ****************************************************************/
9987
9988 WERROR _spoolss_61(pipes_struct *p,
9989                    struct spoolss_61 *r)
9990 {
9991         p->rng_fault_state = true;
9992         return WERR_NOT_SUPPORTED;
9993 }
9994
9995 /****************************************************************
9996  _spoolss_62
9997 ****************************************************************/
9998
9999 WERROR _spoolss_62(pipes_struct *p,
10000                    struct spoolss_62 *r)
10001 {
10002         p->rng_fault_state = true;
10003         return WERR_NOT_SUPPORTED;
10004 }
10005
10006 /****************************************************************
10007  _spoolss_63
10008 ****************************************************************/
10009
10010 WERROR _spoolss_63(pipes_struct *p,
10011                    struct spoolss_63 *r)
10012 {
10013         p->rng_fault_state = true;
10014         return WERR_NOT_SUPPORTED;
10015 }
10016
10017 /****************************************************************
10018  _spoolss_64
10019 ****************************************************************/
10020
10021 WERROR _spoolss_64(pipes_struct *p,
10022                    struct spoolss_64 *r)
10023 {
10024         p->rng_fault_state = true;
10025         return WERR_NOT_SUPPORTED;
10026 }
10027
10028 /****************************************************************
10029  _spoolss_65
10030 ****************************************************************/
10031
10032 WERROR _spoolss_65(pipes_struct *p,
10033                    struct spoolss_65 *r)
10034 {
10035         p->rng_fault_state = true;
10036         return WERR_NOT_SUPPORTED;
10037 }
10038
10039 /****************************************************************
10040  _spoolss_GetCorePrinterDrivers
10041 ****************************************************************/
10042
10043 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10044                                       struct spoolss_GetCorePrinterDrivers *r)
10045 {
10046         p->rng_fault_state = true;
10047         return WERR_NOT_SUPPORTED;
10048 }
10049
10050 /****************************************************************
10051  _spoolss_67
10052 ****************************************************************/
10053
10054 WERROR _spoolss_67(pipes_struct *p,
10055                    struct spoolss_67 *r)
10056 {
10057         p->rng_fault_state = true;
10058         return WERR_NOT_SUPPORTED;
10059 }
10060
10061 /****************************************************************
10062  _spoolss_GetPrinterDriverPackagePath
10063 ****************************************************************/
10064
10065 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10066                                             struct spoolss_GetPrinterDriverPackagePath *r)
10067 {
10068         p->rng_fault_state = true;
10069         return WERR_NOT_SUPPORTED;
10070 }
10071
10072 /****************************************************************
10073  _spoolss_69
10074 ****************************************************************/
10075
10076 WERROR _spoolss_69(pipes_struct *p,
10077                    struct spoolss_69 *r)
10078 {
10079         p->rng_fault_state = true;
10080         return WERR_NOT_SUPPORTED;
10081 }
10082
10083 /****************************************************************
10084  _spoolss_6a
10085 ****************************************************************/
10086
10087 WERROR _spoolss_6a(pipes_struct *p,
10088                    struct spoolss_6a *r)
10089 {
10090         p->rng_fault_state = true;
10091         return WERR_NOT_SUPPORTED;
10092 }
10093
10094 /****************************************************************
10095  _spoolss_6b
10096 ****************************************************************/
10097
10098 WERROR _spoolss_6b(pipes_struct *p,
10099                    struct spoolss_6b *r)
10100 {
10101         p->rng_fault_state = true;
10102         return WERR_NOT_SUPPORTED;
10103 }
10104
10105 /****************************************************************
10106  _spoolss_6c
10107 ****************************************************************/
10108
10109 WERROR _spoolss_6c(pipes_struct *p,
10110                    struct spoolss_6c *r)
10111 {
10112         p->rng_fault_state = true;
10113         return WERR_NOT_SUPPORTED;
10114 }
10115
10116 /****************************************************************
10117  _spoolss_6d
10118 ****************************************************************/
10119
10120 WERROR _spoolss_6d(pipes_struct *p,
10121                    struct spoolss_6d *r)
10122 {
10123         p->rng_fault_state = true;
10124         return WERR_NOT_SUPPORTED;
10125 }