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