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