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