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