s3: Lift the server_messaging_context from construct_printer_info2
[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(struct messaging_context *msg_ctx,
2476                                        int snum,
2477                                        struct spoolss_Notify *data,
2478                                        print_queue_struct *queue,
2479                                        struct spoolss_PrinterInfo2 *pinfo2,
2480                                        TALLOC_CTX *mem_ctx)
2481 {
2482         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2483 }
2484
2485 /*******************************************************************
2486  * fill a notify_info_data with the printername (not including the servername).
2487  ********************************************************************/
2488
2489 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2490                                         int snum,
2491                                         struct spoolss_Notify *data,
2492                                         print_queue_struct *queue,
2493                                         struct spoolss_PrinterInfo2 *pinfo2,
2494                                         TALLOC_CTX *mem_ctx)
2495 {
2496         /* the notify name should not contain the \\server\ part */
2497         const char *p = strrchr(pinfo2->printername, '\\');
2498
2499         if (!p) {
2500                 p = pinfo2->printername;
2501         } else {
2502                 p++;
2503         }
2504
2505         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2506 }
2507
2508 /*******************************************************************
2509  * fill a notify_info_data with the servicename
2510  ********************************************************************/
2511
2512 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2513                                       int snum,
2514                                       struct spoolss_Notify *data,
2515                                       print_queue_struct *queue,
2516                                       struct spoolss_PrinterInfo2 *pinfo2,
2517                                       TALLOC_CTX *mem_ctx)
2518 {
2519         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2520 }
2521
2522 /*******************************************************************
2523  * fill a notify_info_data with the port name
2524  ********************************************************************/
2525
2526 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2527                                      int snum,
2528                                      struct spoolss_Notify *data,
2529                                      print_queue_struct *queue,
2530                                      struct spoolss_PrinterInfo2 *pinfo2,
2531                                      TALLOC_CTX *mem_ctx)
2532 {
2533         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2534 }
2535
2536 /*******************************************************************
2537  * fill a notify_info_data with the printername
2538  * but it doesn't exist, have to see what to do
2539  ********************************************************************/
2540
2541 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2542                                        int snum,
2543                                        struct spoolss_Notify *data,
2544                                        print_queue_struct *queue,
2545                                        struct spoolss_PrinterInfo2 *pinfo2,
2546                                        TALLOC_CTX *mem_ctx)
2547 {
2548         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2549 }
2550
2551 /*******************************************************************
2552  * fill a notify_info_data with the comment
2553  ********************************************************************/
2554
2555 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2556                                    int snum,
2557                                    struct spoolss_Notify *data,
2558                                    print_queue_struct *queue,
2559                                    struct spoolss_PrinterInfo2 *pinfo2,
2560                                    TALLOC_CTX *mem_ctx)
2561 {
2562         const char *p;
2563
2564         if (*pinfo2->comment == '\0') {
2565                 p = lp_comment(snum);
2566         } else {
2567                 p = pinfo2->comment;
2568         }
2569
2570         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2571 }
2572
2573 /*******************************************************************
2574  * fill a notify_info_data with the comment
2575  * location = "Room 1, floor 2, building 3"
2576  ********************************************************************/
2577
2578 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2579                                     int snum,
2580                                     struct spoolss_Notify *data,
2581                                     print_queue_struct *queue,
2582                                     struct spoolss_PrinterInfo2 *pinfo2,
2583                                     TALLOC_CTX *mem_ctx)
2584 {
2585         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2586 }
2587
2588 /*******************************************************************
2589  * fill a notify_info_data with the device mode
2590  * jfm:xxxx don't to it for know but that's a real problem !!!
2591  ********************************************************************/
2592
2593 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2594                                    int snum,
2595                                    struct spoolss_Notify *data,
2596                                    print_queue_struct *queue,
2597                                    struct spoolss_PrinterInfo2 *pinfo2,
2598                                    TALLOC_CTX *mem_ctx)
2599 {
2600         /* for a dummy implementation we have to zero the fields */
2601         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2602 }
2603
2604 /*******************************************************************
2605  * fill a notify_info_data with the separator file name
2606  ********************************************************************/
2607
2608 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2609                                    int snum,
2610                                    struct spoolss_Notify *data,
2611                                    print_queue_struct *queue,
2612                                    struct spoolss_PrinterInfo2 *pinfo2,
2613                                    TALLOC_CTX *mem_ctx)
2614 {
2615         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2616 }
2617
2618 /*******************************************************************
2619  * fill a notify_info_data with the print processor
2620  * jfm:xxxx return always winprint to indicate we don't do anything to it
2621  ********************************************************************/
2622
2623 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2624                                            int snum,
2625                                            struct spoolss_Notify *data,
2626                                            print_queue_struct *queue,
2627                                            struct spoolss_PrinterInfo2 *pinfo2,
2628                                            TALLOC_CTX *mem_ctx)
2629 {
2630         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2631 }
2632
2633 /*******************************************************************
2634  * fill a notify_info_data with the print processor options
2635  * jfm:xxxx send an empty string
2636  ********************************************************************/
2637
2638 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2639                                       int snum,
2640                                       struct spoolss_Notify *data,
2641                                       print_queue_struct *queue,
2642                                       struct spoolss_PrinterInfo2 *pinfo2,
2643                                       TALLOC_CTX *mem_ctx)
2644 {
2645         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2646 }
2647
2648 /*******************************************************************
2649  * fill a notify_info_data with the data type
2650  * jfm:xxxx always send RAW as data type
2651  ********************************************************************/
2652
2653 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2654                                     int snum,
2655                                     struct spoolss_Notify *data,
2656                                     print_queue_struct *queue,
2657                                     struct spoolss_PrinterInfo2 *pinfo2,
2658                                     TALLOC_CTX *mem_ctx)
2659 {
2660         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2661 }
2662
2663 /*******************************************************************
2664  * fill a notify_info_data with the security descriptor
2665  * jfm:xxxx send an null pointer to say no security desc
2666  * have to implement security before !
2667  ********************************************************************/
2668
2669 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2670                                          int snum,
2671                                          struct spoolss_Notify *data,
2672                                          print_queue_struct *queue,
2673                                          struct spoolss_PrinterInfo2 *pinfo2,
2674                                          TALLOC_CTX *mem_ctx)
2675 {
2676         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2677 }
2678
2679 /*******************************************************************
2680  * fill a notify_info_data with the attributes
2681  * jfm:xxxx a samba printer is always shared
2682  ********************************************************************/
2683
2684 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2685                                       int snum,
2686                                       struct spoolss_Notify *data,
2687                                       print_queue_struct *queue,
2688                                       struct spoolss_PrinterInfo2 *pinfo2,
2689                                       TALLOC_CTX *mem_ctx)
2690 {
2691         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2692 }
2693
2694 /*******************************************************************
2695  * fill a notify_info_data with the priority
2696  ********************************************************************/
2697
2698 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2699                                     int snum,
2700                                     struct spoolss_Notify *data,
2701                                     print_queue_struct *queue,
2702                                     struct spoolss_PrinterInfo2 *pinfo2,
2703                                     TALLOC_CTX *mem_ctx)
2704 {
2705         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2706 }
2707
2708 /*******************************************************************
2709  * fill a notify_info_data with the default priority
2710  ********************************************************************/
2711
2712 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2713                                             int snum,
2714                                             struct spoolss_Notify *data,
2715                                             print_queue_struct *queue,
2716                                             struct spoolss_PrinterInfo2 *pinfo2,
2717                                             TALLOC_CTX *mem_ctx)
2718 {
2719         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2720 }
2721
2722 /*******************************************************************
2723  * fill a notify_info_data with the start time
2724  ********************************************************************/
2725
2726 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2727                                       int snum,
2728                                       struct spoolss_Notify *data,
2729                                       print_queue_struct *queue,
2730                                       struct spoolss_PrinterInfo2 *pinfo2,
2731                                       TALLOC_CTX *mem_ctx)
2732 {
2733         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2734 }
2735
2736 /*******************************************************************
2737  * fill a notify_info_data with the until time
2738  ********************************************************************/
2739
2740 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2741                                       int snum,
2742                                       struct spoolss_Notify *data,
2743                                       print_queue_struct *queue,
2744                                       struct spoolss_PrinterInfo2 *pinfo2,
2745                                       TALLOC_CTX *mem_ctx)
2746 {
2747         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2748 }
2749
2750 /*******************************************************************
2751  * fill a notify_info_data with the status
2752  ********************************************************************/
2753
2754 static void spoolss_notify_status(struct messaging_context *msg_ctx,
2755                                   int snum,
2756                                   struct spoolss_Notify *data,
2757                                   print_queue_struct *queue,
2758                                   struct spoolss_PrinterInfo2 *pinfo2,
2759                                   TALLOC_CTX *mem_ctx)
2760 {
2761         print_status_struct status;
2762
2763         print_queue_length(msg_ctx, snum, &status);
2764         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2765 }
2766
2767 /*******************************************************************
2768  * fill a notify_info_data with the number of jobs queued
2769  ********************************************************************/
2770
2771 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
2772                                  int snum,
2773                                  struct spoolss_Notify *data,
2774                                  print_queue_struct *queue,
2775                                  struct spoolss_PrinterInfo2 *pinfo2,
2776                                  TALLOC_CTX *mem_ctx)
2777 {
2778         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
2779                 data, print_queue_length(msg_ctx, snum, NULL));
2780 }
2781
2782 /*******************************************************************
2783  * fill a notify_info_data with the average ppm
2784  ********************************************************************/
2785
2786 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
2787                                        int snum,
2788                                        struct spoolss_Notify *data,
2789                                        print_queue_struct *queue,
2790                                        struct spoolss_PrinterInfo2 *pinfo2,
2791                                        TALLOC_CTX *mem_ctx)
2792 {
2793         /* always respond 8 pages per minutes */
2794         /* a little hard ! */
2795         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2796 }
2797
2798 /*******************************************************************
2799  * fill a notify_info_data with username
2800  ********************************************************************/
2801
2802 static void spoolss_notify_username(struct messaging_context *msg_ctx,
2803                                     int snum,
2804                                     struct spoolss_Notify *data,
2805                                     print_queue_struct *queue,
2806                                     struct spoolss_PrinterInfo2 *pinfo2,
2807                                     TALLOC_CTX *mem_ctx)
2808 {
2809         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2810 }
2811
2812 /*******************************************************************
2813  * fill a notify_info_data with job status
2814  ********************************************************************/
2815
2816 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
2817                                       int snum,
2818                                       struct spoolss_Notify *data,
2819                                       print_queue_struct *queue,
2820                                       struct spoolss_PrinterInfo2 *pinfo2,
2821                                       TALLOC_CTX *mem_ctx)
2822 {
2823         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2824 }
2825
2826 /*******************************************************************
2827  * fill a notify_info_data with job name
2828  ********************************************************************/
2829
2830 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
2831                                     int snum,
2832                                     struct spoolss_Notify *data,
2833                                     print_queue_struct *queue,
2834                                     struct spoolss_PrinterInfo2 *pinfo2,
2835                                     TALLOC_CTX *mem_ctx)
2836 {
2837         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2838 }
2839
2840 /*******************************************************************
2841  * fill a notify_info_data with job status
2842  ********************************************************************/
2843
2844 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
2845                                              int snum,
2846                                              struct spoolss_Notify *data,
2847                                              print_queue_struct *queue,
2848                                              struct spoolss_PrinterInfo2 *pinfo2,
2849                                              TALLOC_CTX *mem_ctx)
2850 {
2851         /*
2852          * Now we're returning job status codes we just return a "" here. JRA.
2853          */
2854
2855         const char *p = "";
2856
2857 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2858         p = "unknown";
2859
2860         switch (queue->status) {
2861         case LPQ_QUEUED:
2862                 p = "Queued";
2863                 break;
2864         case LPQ_PAUSED:
2865                 p = "";    /* NT provides the paused string */
2866                 break;
2867         case LPQ_SPOOLING:
2868                 p = "Spooling";
2869                 break;
2870         case LPQ_PRINTING:
2871                 p = "Printing";
2872                 break;
2873         }
2874 #endif /* NO LONGER NEEDED. */
2875
2876         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2877 }
2878
2879 /*******************************************************************
2880  * fill a notify_info_data with job time
2881  ********************************************************************/
2882
2883 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
2884                                     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, 0);
2891 }
2892
2893 /*******************************************************************
2894  * fill a notify_info_data with job size
2895  ********************************************************************/
2896
2897 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
2898                                     int snum,
2899                                     struct spoolss_Notify *data,
2900                                     print_queue_struct *queue,
2901                                     struct spoolss_PrinterInfo2 *pinfo2,
2902                                     TALLOC_CTX *mem_ctx)
2903 {
2904         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2905 }
2906
2907 /*******************************************************************
2908  * fill a notify_info_data with page info
2909  ********************************************************************/
2910 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
2911                                        int snum,
2912                                 struct spoolss_Notify *data,
2913                                 print_queue_struct *queue,
2914                                 struct spoolss_PrinterInfo2 *pinfo2,
2915                                 TALLOC_CTX *mem_ctx)
2916 {
2917         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2918 }
2919
2920 /*******************************************************************
2921  * fill a notify_info_data with pages printed info.
2922  ********************************************************************/
2923 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
2924                                          int snum,
2925                                 struct spoolss_Notify *data,
2926                                 print_queue_struct *queue,
2927                                 struct spoolss_PrinterInfo2 *pinfo2,
2928                                 TALLOC_CTX *mem_ctx)
2929 {
2930         /* Add code when back-end tracks this */
2931         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2932 }
2933
2934 /*******************************************************************
2935  Fill a notify_info_data with job position.
2936  ********************************************************************/
2937
2938 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
2939                                         int snum,
2940                                         struct spoolss_Notify *data,
2941                                         print_queue_struct *queue,
2942                                         struct spoolss_PrinterInfo2 *pinfo2,
2943                                         TALLOC_CTX *mem_ctx)
2944 {
2945         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2946 }
2947
2948 /*******************************************************************
2949  Fill a notify_info_data with submitted time.
2950  ********************************************************************/
2951
2952 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
2953                                           int snum,
2954                                           struct spoolss_Notify *data,
2955                                           print_queue_struct *queue,
2956                                           struct spoolss_PrinterInfo2 *pinfo2,
2957                                           TALLOC_CTX *mem_ctx)
2958 {
2959         data->data.string.string = NULL;
2960         data->data.string.size = 0;
2961
2962         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2963                                &data->data.string.string,
2964                                &data->data.string.size);
2965
2966 }
2967
2968 struct s_notify_info_data_table
2969 {
2970         enum spoolss_NotifyType type;
2971         uint16_t field;
2972         const char *name;
2973         enum spoolss_NotifyTable variable_type;
2974         void (*fn) (struct messaging_context *msg_ctx,
2975                     int snum, struct spoolss_Notify *data,
2976                     print_queue_struct *queue,
2977                     struct spoolss_PrinterInfo2 *pinfo2,
2978                     TALLOC_CTX *mem_ctx);
2979 };
2980
2981 /* A table describing the various print notification constants and
2982    whether the notification data is a pointer to a variable sized
2983    buffer, a one value uint32_t or a two value uint32_t. */
2984
2985 static const struct s_notify_info_data_table notify_info_data_table[] =
2986 {
2987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3004 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3005 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3006 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3007 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3008 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3009 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3010 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3011 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3012 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3013 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3014 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3015 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3016 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3017 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3018 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3019 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3020 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3021 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3022 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3023 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3024 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3025 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3026 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3027 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3028 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3029 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3030 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3031 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3032 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3033 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3034 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3035 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3036 };
3037
3038 /*******************************************************************
3039  Return the variable_type of info_data structure.
3040 ********************************************************************/
3041
3042 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3043                                                   uint16_t field)
3044 {
3045         int i=0;
3046
3047         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3048                 if ( (notify_info_data_table[i].type == type) &&
3049                      (notify_info_data_table[i].field == field) ) {
3050                         return notify_info_data_table[i].variable_type;
3051                 }
3052         }
3053
3054         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3055
3056         return 0;
3057 }
3058
3059 /****************************************************************************
3060 ****************************************************************************/
3061
3062 static bool search_notify(enum spoolss_NotifyType type,
3063                           uint16_t field,
3064                           int *value)
3065 {
3066         int i;
3067
3068         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3069                 if (notify_info_data_table[i].type == type &&
3070                     notify_info_data_table[i].field == field &&
3071                     notify_info_data_table[i].fn != NULL) {
3072                         *value = i;
3073                         return true;
3074                 }
3075         }
3076
3077         return false;
3078 }
3079
3080 /****************************************************************************
3081 ****************************************************************************/
3082
3083 static void construct_info_data(struct spoolss_Notify *info_data,
3084                                 enum spoolss_NotifyType type,
3085                                 uint16_t field, int id)
3086 {
3087         info_data->type                 = type;
3088         info_data->field.field          = field;
3089         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3090         info_data->job_id               = id;
3091 }
3092
3093 /*******************************************************************
3094  *
3095  * fill a notify_info struct with info asked
3096  *
3097  ********************************************************************/
3098
3099 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3100                                           Printer_entry *print_hnd,
3101                                           struct spoolss_NotifyInfo *info,
3102                                           struct spoolss_PrinterInfo2 *pinfo2,
3103                                           int snum,
3104                                           const struct spoolss_NotifyOptionType *option_type,
3105                                           uint32_t id,
3106                                           TALLOC_CTX *mem_ctx)
3107 {
3108         int field_num,j;
3109         enum spoolss_NotifyType type;
3110         uint16_t field;
3111
3112         struct spoolss_Notify *current_data;
3113         print_queue_struct *queue=NULL;
3114
3115         type = option_type->type;
3116
3117         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3118                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3119                 option_type->count, lp_servicename(snum)));
3120
3121         for(field_num=0; field_num < option_type->count; field_num++) {
3122                 field = option_type->fields[field_num].field;
3123
3124                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3125
3126                 if (!search_notify(type, field, &j) )
3127                         continue;
3128
3129                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3130                                                       struct spoolss_Notify,
3131                                                       info->count + 1);
3132                 if (info->notifies == NULL) {
3133                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3134                         return false;
3135                 }
3136
3137                 current_data = &info->notifies[info->count];
3138
3139                 construct_info_data(current_data, type, field, id);
3140
3141                 DEBUG(10, ("construct_notify_printer_info: "
3142                            "calling [%s]  snum=%d  printername=[%s])\n",
3143                            notify_info_data_table[j].name, snum,
3144                            pinfo2->printername));
3145
3146                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3147                                              queue, pinfo2, mem_ctx);
3148
3149                 info->count++;
3150         }
3151
3152         return true;
3153 }
3154
3155 /*******************************************************************
3156  *
3157  * fill a notify_info struct with info asked
3158  *
3159  ********************************************************************/
3160
3161 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3162                                        print_queue_struct *queue,
3163                                        struct spoolss_NotifyInfo *info,
3164                                        struct spoolss_PrinterInfo2 *pinfo2,
3165                                        int snum,
3166                                        const struct spoolss_NotifyOptionType *option_type,
3167                                        uint32_t id,
3168                                        TALLOC_CTX *mem_ctx)
3169 {
3170         int field_num,j;
3171         enum spoolss_NotifyType type;
3172         uint16_t field;
3173         struct spoolss_Notify *current_data;
3174
3175         DEBUG(4,("construct_notify_jobs_info\n"));
3176
3177         type = option_type->type;
3178
3179         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3180                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3181                 option_type->count));
3182
3183         for(field_num=0; field_num<option_type->count; field_num++) {
3184                 field = option_type->fields[field_num].field;
3185
3186                 if (!search_notify(type, field, &j) )
3187                         continue;
3188
3189                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3190                                                       struct spoolss_Notify,
3191                                                       info->count + 1);
3192                 if (info->notifies == NULL) {
3193                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3194                         return false;
3195                 }
3196
3197                 current_data=&(info->notifies[info->count]);
3198
3199                 construct_info_data(current_data, type, field, id);
3200                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3201                                              queue, pinfo2, mem_ctx);
3202                 info->count++;
3203         }
3204
3205         return true;
3206 }
3207
3208 /*
3209  * JFM: The enumeration is not that simple, it's even non obvious.
3210  *
3211  * let's take an example: I want to monitor the PRINTER SERVER for
3212  * the printer's name and the number of jobs currently queued.
3213  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3214  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3215  *
3216  * I have 3 printers on the back of my server.
3217  *
3218  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3219  * structures.
3220  *   Number     Data                    Id
3221  *      1       printer 1 name          1
3222  *      2       printer 1 cjob          1
3223  *      3       printer 2 name          2
3224  *      4       printer 2 cjob          2
3225  *      5       printer 3 name          3
3226  *      6       printer 3 name          3
3227  *
3228  * that's the print server case, the printer case is even worse.
3229  */
3230
3231 /*******************************************************************
3232  *
3233  * enumerate all printers on the printserver
3234  * fill a notify_info struct with info asked
3235  *
3236  ********************************************************************/
3237
3238 static WERROR printserver_notify_info(struct pipes_struct *p,
3239                                       struct policy_handle *hnd,
3240                                       struct spoolss_NotifyInfo *info,
3241                                       TALLOC_CTX *mem_ctx)
3242 {
3243         int snum;
3244         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3245         int n_services=lp_numservices();
3246         int i;
3247         struct spoolss_NotifyOption *option;
3248         struct spoolss_NotifyOptionType option_type;
3249         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3250         WERROR result;
3251
3252         DEBUG(4,("printserver_notify_info\n"));
3253
3254         if (!Printer)
3255                 return WERR_BADFID;
3256
3257         option = Printer->notify.option;
3258
3259         info->version   = 2;
3260         info->notifies  = NULL;
3261         info->count     = 0;
3262
3263         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3264            sending a ffpcn() request first */
3265
3266         if ( !option )
3267                 return WERR_BADFID;
3268
3269         for (i=0; i<option->count; i++) {
3270                 option_type = option->types[i];
3271
3272                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3273                         continue;
3274
3275                 for (snum = 0; snum < n_services; snum++) {
3276                         if (!lp_browseable(snum) ||
3277                             !lp_snum_ok(snum) ||
3278                             !lp_print_ok(snum)) {
3279                                 continue; /* skip */
3280                         }
3281
3282                         /* Maybe we should use the SYSTEM server_info here... */
3283                         result = winreg_get_printer(mem_ctx, p->server_info,
3284                                                     p->msg_ctx,
3285                                                     Printer->servername,
3286                                                     lp_servicename(snum),
3287                                                     &pinfo2);
3288                         if (!W_ERROR_IS_OK(result)) {
3289                                 DEBUG(4, ("printserver_notify_info: "
3290                                           "Failed to get printer [%s]\n",
3291                                           lp_servicename(snum)));
3292                                 continue;
3293                         }
3294
3295
3296                         construct_notify_printer_info(p->msg_ctx,
3297                                                       Printer, info,
3298                                                       pinfo2, snum,
3299                                                       &option_type, snum,
3300                                                       mem_ctx);
3301
3302                         TALLOC_FREE(pinfo2);
3303                 }
3304         }
3305
3306 #if 0
3307         /*
3308          * Debugging information, don't delete.
3309          */
3310
3311         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3312         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3313         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3314
3315         for (i=0; i<info->count; i++) {
3316                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3317                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3318                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3319         }
3320 #endif
3321
3322         return WERR_OK;
3323 }
3324
3325 /*******************************************************************
3326  *
3327  * fill a notify_info struct with info asked
3328  *
3329  ********************************************************************/
3330
3331 static WERROR printer_notify_info(struct pipes_struct *p,
3332                                   struct policy_handle *hnd,
3333                                   struct spoolss_NotifyInfo *info,
3334                                   TALLOC_CTX *mem_ctx)
3335 {
3336         int snum;
3337         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3338         int i;
3339         uint32_t id;
3340         struct spoolss_NotifyOption *option;
3341         struct spoolss_NotifyOptionType option_type;
3342         int count,j;
3343         print_queue_struct *queue=NULL;
3344         print_status_struct status;
3345         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3346         WERROR result;
3347
3348         DEBUG(4,("printer_notify_info\n"));
3349
3350         if (!Printer)
3351                 return WERR_BADFID;
3352
3353         option = Printer->notify.option;
3354         id = 0x0;
3355
3356         info->version   = 2;
3357         info->notifies  = NULL;
3358         info->count     = 0;
3359
3360         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3361            sending a ffpcn() request first */
3362
3363         if ( !option )
3364                 return WERR_BADFID;
3365
3366         get_printer_snum(p, hnd, &snum, NULL);
3367
3368         /* Maybe we should use the SYSTEM server_info here... */
3369         result = winreg_get_printer(mem_ctx, p->server_info, p->msg_ctx,
3370                                     Printer->servername,
3371                                     lp_servicename(snum), &pinfo2);
3372         if (!W_ERROR_IS_OK(result)) {
3373                 return WERR_BADFID;
3374         }
3375
3376         for (i=0; i<option->count; i++) {
3377                 option_type = option->types[i];
3378
3379                 switch (option_type.type) {
3380                 case PRINTER_NOTIFY_TYPE:
3381                         if (construct_notify_printer_info(p->msg_ctx,
3382                                                           Printer, info,
3383                                                           pinfo2, snum,
3384                                                           &option_type, id,
3385                                                           mem_ctx)) {
3386                                 id--;
3387                         }
3388                         break;
3389
3390                 case JOB_NOTIFY_TYPE:
3391
3392                         count = print_queue_status(p->msg_ctx, snum, &queue,
3393                                                    &status);
3394
3395                         for (j=0; j<count; j++) {
3396                                 construct_notify_jobs_info(p->msg_ctx,
3397                                                            &queue[j], info,
3398                                                            pinfo2, snum,
3399                                                            &option_type,
3400                                                            queue[j].job,
3401                                                            mem_ctx);
3402                         }
3403
3404                         SAFE_FREE(queue);
3405                         break;
3406                 }
3407         }
3408
3409         /*
3410          * Debugging information, don't delete.
3411          */
3412         /*
3413         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3414         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3415         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3416
3417         for (i=0; i<info->count; i++) {
3418                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3419                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3420                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3421         }
3422         */
3423
3424         talloc_free(pinfo2);
3425         return WERR_OK;
3426 }
3427
3428 /****************************************************************
3429  _spoolss_RouterRefreshPrinterChangeNotify
3430 ****************************************************************/
3431
3432 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3433                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3434 {
3435         struct spoolss_NotifyInfo *info;
3436
3437         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3438         WERROR result = WERR_BADFID;
3439
3440         /* we always have a spoolss_NotifyInfo struct */
3441         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3442         if (!info) {
3443                 result = WERR_NOMEM;
3444                 goto done;
3445         }
3446
3447         *r->out.info = info;
3448
3449         if (!Printer) {
3450                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3451                         "Invalid handle (%s:%u:%u).\n",
3452                         OUR_HANDLE(r->in.handle)));
3453                 goto done;
3454         }
3455
3456         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3457
3458         /*
3459          *      We are now using the change value, and
3460          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3461          *      I don't have a global notification system, I'm sending back all the
3462          *      informations even when _NOTHING_ has changed.
3463          */
3464
3465         /* We need to keep track of the change value to send back in
3466            RRPCN replies otherwise our updates are ignored. */
3467
3468         Printer->notify.fnpcn = true;
3469
3470         if (Printer->notify.client_connected) {
3471                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3472                         "Saving change value in request [%x]\n",
3473                         r->in.change_low));
3474                 Printer->notify.change = r->in.change_low;
3475         }
3476
3477         /* just ignore the spoolss_NotifyOption */
3478
3479         switch (Printer->printer_type) {
3480                 case SPLHND_SERVER:
3481                         result = printserver_notify_info(p, r->in.handle,
3482                                                          info, p->mem_ctx);
3483                         break;
3484
3485                 case SPLHND_PRINTER:
3486                         result = printer_notify_info(p, r->in.handle,
3487                                                      info, p->mem_ctx);
3488                         break;
3489         }
3490
3491         Printer->notify.fnpcn = false;
3492
3493 done:
3494         return result;
3495 }
3496
3497 /********************************************************************
3498  * construct_printer_info_0
3499  * fill a printer_info_0 struct
3500  ********************************************************************/
3501
3502 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3503                                       struct auth_serversupplied_info *server_info,
3504                                       struct messaging_context *msg_ctx,
3505                                       struct spoolss_PrinterInfo2 *info2,
3506                                       struct spoolss_PrinterInfo0 *r,
3507                                       int snum)
3508 {
3509         int count;
3510         counter_printer_0 *session_counter;
3511         struct timeval setuptime;
3512         print_status_struct status;
3513
3514         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3515         W_ERROR_HAVE_NO_MEMORY(r->printername);
3516
3517         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3518         W_ERROR_HAVE_NO_MEMORY(r->servername);
3519
3520         count = print_queue_length(msg_ctx, snum, &status);
3521
3522         /* check if we already have a counter for this printer */
3523         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3524                 if (session_counter->snum == snum)
3525                         break;
3526         }
3527
3528         /* it's the first time, add it to the list */
3529         if (session_counter == NULL) {
3530                 session_counter = SMB_MALLOC_P(counter_printer_0);
3531                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3532                 ZERO_STRUCTP(session_counter);
3533                 session_counter->snum           = snum;
3534                 session_counter->counter        = 0;
3535                 DLIST_ADD(counter_list, session_counter);
3536         }
3537
3538         /* increment it */
3539         session_counter->counter++;
3540
3541         r->cjobs                        = count;
3542         r->total_jobs                   = 0;
3543         r->total_bytes                  = 0;
3544
3545         get_startup_time(&setuptime);
3546         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3547
3548         /* JFM:
3549          * the global_counter should be stored in a TDB as it's common to all the clients
3550          * and should be zeroed on samba startup
3551          */
3552         r->global_counter               = session_counter->counter;
3553         r->total_pages                  = 0;
3554         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3555         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3556         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3557         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3558         r->spooling                     = 0;
3559         r->max_spooling                 = 0;
3560         r->session_counter              = session_counter->counter;
3561         r->num_error_out_of_paper       = 0x0;
3562         r->num_error_not_ready          = 0x0;          /* number of print failure */
3563         r->job_error                    = 0x0;
3564         r->number_of_processors         = 0x1;
3565         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3566         r->high_part_total_bytes        = 0x0;
3567
3568         /* ChangeID in milliseconds*/
3569         winreg_printer_get_changeid(mem_ctx, server_info, msg_ctx,
3570                                     info2->sharename, &r->change_id);
3571
3572         r->last_error                   = WERR_OK;
3573         r->status                       = nt_printq_status(status.status);
3574         r->enumerate_network_printers   = 0x0;
3575         r->c_setprinter                 = 0x0;
3576         r->processor_architecture       = 0x0;
3577         r->processor_level              = 0x6;          /* 6  ???*/
3578         r->ref_ic                       = 0;
3579         r->reserved2                    = 0;
3580         r->reserved3                    = 0;
3581
3582         return WERR_OK;
3583 }
3584
3585
3586 /********************************************************************
3587  * construct_printer_info1
3588  * fill a spoolss_PrinterInfo1 struct
3589 ********************************************************************/
3590
3591 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3592                                       const struct spoolss_PrinterInfo2 *info2,
3593                                       uint32_t flags,
3594                                       struct spoolss_PrinterInfo1 *r,
3595                                       int snum)
3596 {
3597         r->flags                = flags;
3598
3599         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3600                                                   info2->printername,
3601                                                   info2->drivername,
3602                                                   info2->location);
3603         W_ERROR_HAVE_NO_MEMORY(r->description);
3604
3605         if (info2->comment == NULL || info2->comment[0] == '\0') {
3606                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3607         } else {
3608                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3609         }
3610         W_ERROR_HAVE_NO_MEMORY(r->comment);
3611
3612         r->name                 = talloc_strdup(mem_ctx, info2->printername);
3613         W_ERROR_HAVE_NO_MEMORY(r->name);
3614
3615         return WERR_OK;
3616 }
3617
3618 /********************************************************************
3619  * construct_printer_info2
3620  * fill a spoolss_PrinterInfo2 struct
3621 ********************************************************************/
3622
3623 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3624                                       struct messaging_context *msg_ctx,
3625                                       const struct spoolss_PrinterInfo2 *info2,
3626                                       struct spoolss_PrinterInfo2 *r,
3627                                       int snum)
3628 {
3629         int count;
3630         print_status_struct status;
3631
3632         count = print_queue_length(msg_ctx, snum, &status);
3633
3634         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3635         W_ERROR_HAVE_NO_MEMORY(r->servername);
3636         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3637         W_ERROR_HAVE_NO_MEMORY(r->printername);
3638         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3639         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3640         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3641         W_ERROR_HAVE_NO_MEMORY(r->portname);
3642         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3643         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3644
3645         if (info2->comment[0] == '\0') {
3646                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3647         } else {
3648                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3649         }
3650         W_ERROR_HAVE_NO_MEMORY(r->comment);
3651
3652         r->location             = talloc_strdup(mem_ctx, info2->location);
3653         W_ERROR_HAVE_NO_MEMORY(r->location);
3654         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3655         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3656         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3657         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3658         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3659         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3660         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3661         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3662
3663         r->attributes           = info2->attributes;
3664
3665         r->priority             = info2->priority;
3666         r->defaultpriority      = info2->defaultpriority;
3667         r->starttime            = info2->starttime;
3668         r->untiltime            = info2->untiltime;
3669         r->status               = nt_printq_status(status.status);
3670         r->cjobs                = count;
3671         r->averageppm           = info2->averageppm;
3672
3673         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3674         if (!r->devmode) {
3675                 DEBUG(8,("Returning NULL Devicemode!\n"));
3676         }
3677
3678         r->secdesc = NULL;
3679
3680         if (info2->secdesc != NULL) {
3681                 /* don't use talloc_steal() here unless you do a deep steal of all
3682                    the SEC_DESC members */
3683
3684                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
3685         }
3686
3687         return WERR_OK;
3688 }
3689
3690 /********************************************************************
3691  * construct_printer_info3
3692  * fill a spoolss_PrinterInfo3 struct
3693  ********************************************************************/
3694
3695 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3696                                       const struct spoolss_PrinterInfo2 *info2,
3697                                       struct spoolss_PrinterInfo3 *r,
3698                                       int snum)
3699 {
3700         /* These are the components of the SD we are returning. */
3701
3702         if (info2->secdesc != NULL) {
3703                 /* don't use talloc_steal() here unless you do a deep steal of all
3704                    the SEC_DESC members */
3705
3706                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3707                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3708         }
3709
3710         return WERR_OK;
3711 }
3712
3713 /********************************************************************
3714  * construct_printer_info4
3715  * fill a spoolss_PrinterInfo4 struct
3716  ********************************************************************/
3717
3718 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3719                                       const struct spoolss_PrinterInfo2 *info2,
3720                                       struct spoolss_PrinterInfo4 *r,
3721                                       int snum)
3722 {
3723         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3724         W_ERROR_HAVE_NO_MEMORY(r->printername);
3725         r->servername   = talloc_strdup(mem_ctx, info2->servername);
3726         W_ERROR_HAVE_NO_MEMORY(r->servername);
3727
3728         r->attributes   = info2->attributes;
3729
3730         return WERR_OK;
3731 }
3732
3733 /********************************************************************
3734  * construct_printer_info5
3735  * fill a spoolss_PrinterInfo5 struct
3736  ********************************************************************/
3737
3738 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3739                                       const struct spoolss_PrinterInfo2 *info2,
3740                                       struct spoolss_PrinterInfo5 *r,
3741                                       int snum)
3742 {
3743         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3744         W_ERROR_HAVE_NO_MEMORY(r->printername);
3745         r->portname     = talloc_strdup(mem_ctx, info2->portname);
3746         W_ERROR_HAVE_NO_MEMORY(r->portname);
3747
3748         r->attributes   = info2->attributes;
3749
3750         /* these two are not used by NT+ according to MSDN */
3751         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3752         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3753
3754         return WERR_OK;
3755 }
3756
3757 /********************************************************************
3758  * construct_printer_info_6
3759  * fill a spoolss_PrinterInfo6 struct
3760  ********************************************************************/
3761
3762 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3763                                       const struct spoolss_PrinterInfo2 *info2,
3764                                       struct spoolss_PrinterInfo6 *r,
3765                                       int snum)
3766 {
3767         int count;
3768         print_status_struct status;
3769
3770         count = print_queue_length(server_messaging_context(), snum, &status);
3771
3772         r->status = nt_printq_status(status.status);
3773
3774         return WERR_OK;
3775 }
3776
3777 /********************************************************************
3778  * construct_printer_info7
3779  * fill a spoolss_PrinterInfo7 struct
3780  ********************************************************************/
3781
3782 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3783                                       struct messaging_context *msg_ctx,
3784                                       Printer_entry *print_hnd,
3785                                       struct spoolss_PrinterInfo7 *r,
3786                                       int snum)
3787 {
3788         struct auth_serversupplied_info *server_info;
3789         struct GUID guid;
3790         NTSTATUS status;
3791
3792         status = make_server_info_system(mem_ctx, &server_info);
3793         if (!NT_STATUS_IS_OK(status)) {
3794                 DEBUG(0, ("construct_printer_info7: "
3795                           "Could not create system server_info\n"));
3796                 return WERR_NOMEM;
3797         }
3798
3799         if (is_printer_published(mem_ctx, server_info, msg_ctx,
3800                                  print_hnd->servername,
3801                                  lp_servicename(snum), &guid, NULL)) {
3802                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3803                 r->action = DSPRINT_PUBLISH;
3804         } else {
3805                 r->guid = talloc_strdup(mem_ctx, "");
3806                 r->action = DSPRINT_UNPUBLISH;
3807         }
3808         W_ERROR_HAVE_NO_MEMORY(r->guid);
3809
3810         TALLOC_FREE(server_info);
3811         return WERR_OK;
3812 }
3813
3814 /********************************************************************
3815  * construct_printer_info8
3816  * fill a spoolss_PrinterInfo8 struct
3817  ********************************************************************/
3818
3819 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3820                                       const struct spoolss_PrinterInfo2 *info2,
3821                                       struct spoolss_DeviceModeInfo *r,
3822                                       int snum)
3823 {
3824         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3825         if (!r->devmode) {
3826                 DEBUG(8,("Returning NULL Devicemode!\n"));
3827         }
3828
3829         return WERR_OK;
3830 }
3831
3832
3833 /********************************************************************
3834 ********************************************************************/
3835
3836 static bool snum_is_shared_printer(int snum)
3837 {
3838         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3839 }
3840
3841 /********************************************************************
3842  Spoolss_enumprinters.
3843 ********************************************************************/
3844
3845 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3846                                            struct auth_serversupplied_info *server_info,
3847                                            struct messaging_context *msg_ctx,
3848                                            uint32_t level,
3849                                            uint32_t flags,
3850                                            union spoolss_PrinterInfo **info_p,
3851                                            uint32_t *count_p)
3852 {
3853         int snum;
3854         int n_services = lp_numservices();
3855         union spoolss_PrinterInfo *info = NULL;
3856         uint32_t count = 0;
3857         WERROR result = WERR_OK;
3858
3859         *count_p = 0;
3860         *info_p = NULL;
3861
3862         for (snum = 0; snum < n_services; snum++) {
3863
3864                 const char *printer;
3865                 struct spoolss_PrinterInfo2 *info2;
3866
3867                 if (!snum_is_shared_printer(snum)) {
3868                         continue;
3869                 }
3870
3871                 printer = lp_const_servicename(snum);
3872
3873                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3874                         printer, snum));
3875
3876                 result = winreg_create_printer(mem_ctx,
3877                                                server_info,
3878                                                msg_ctx,
3879                                                NULL,
3880                                                printer);
3881                 if (!W_ERROR_IS_OK(result)) {
3882                         goto out;
3883                 }
3884
3885                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3886                                             union spoolss_PrinterInfo,
3887                                             count + 1);
3888                 if (!info) {
3889                         result = WERR_NOMEM;
3890                         goto out;
3891                 }
3892
3893                 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
3894                                             NULL, printer, &info2);
3895                 if (!W_ERROR_IS_OK(result)) {
3896                         goto out;
3897                 }
3898
3899                 switch (level) {
3900                 case 0:
3901                         result = construct_printer_info0(info, server_info,
3902                                                          msg_ctx, info2,
3903                                                          &info[count].info0, snum);
3904                         break;
3905                 case 1:
3906                         result = construct_printer_info1(info, info2, flags,
3907                                                          &info[count].info1, snum);
3908                         break;
3909                 case 2:
3910                         result = construct_printer_info2(info, msg_ctx, info2,
3911                                                          &info[count].info2, snum);
3912                         break;
3913                 case 4:
3914                         result = construct_printer_info4(info, info2,
3915                                                          &info[count].info4, snum);
3916                         break;
3917                 case 5:
3918                         result = construct_printer_info5(info, info2,
3919                                                          &info[count].info5, snum);
3920                         break;
3921
3922                 default:
3923                         result = WERR_UNKNOWN_LEVEL;
3924                         goto out;
3925                 }
3926
3927                 if (!W_ERROR_IS_OK(result)) {
3928                         goto out;
3929                 }
3930
3931                 count++;
3932         }
3933
3934         *count_p = count;
3935         *info_p = info;
3936
3937  out:
3938         if (!W_ERROR_IS_OK(result)) {
3939                 TALLOC_FREE(info);
3940                 return result;
3941         }
3942
3943         *info_p = info;
3944
3945         return WERR_OK;
3946 }
3947
3948 /********************************************************************
3949  * handle enumeration of printers at level 0
3950  ********************************************************************/
3951
3952 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3953                                   struct auth_serversupplied_info *server_info,
3954                                   struct messaging_context *msg_ctx,
3955                                   uint32_t flags,
3956                                   const char *servername,
3957                                   union spoolss_PrinterInfo **info,
3958                                   uint32_t *count)
3959 {
3960         DEBUG(4,("enum_all_printers_info_0\n"));
3961
3962         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
3963                                             0, flags, info, count);
3964 }
3965
3966
3967 /********************************************************************
3968 ********************************************************************/
3969
3970 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3971                                        struct auth_serversupplied_info *server_info,
3972                                        struct messaging_context *msg_ctx,
3973                                        uint32_t flags,
3974                                        union spoolss_PrinterInfo **info,
3975                                        uint32_t *count)
3976 {
3977         DEBUG(4,("enum_all_printers_info_1\n"));
3978
3979         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
3980                                             1, flags, info, count);
3981 }
3982
3983 /********************************************************************
3984  enum_all_printers_info_1_local.
3985 *********************************************************************/
3986
3987 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3988                                              struct auth_serversupplied_info *server_info,
3989                                              struct messaging_context *msg_ctx,
3990                                              union spoolss_PrinterInfo **info,
3991                                              uint32_t *count)
3992 {
3993         DEBUG(4,("enum_all_printers_info_1_local\n"));
3994
3995         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
3996                                         PRINTER_ENUM_ICON8, info, count);
3997 }
3998
3999 /********************************************************************
4000  enum_all_printers_info_1_name.
4001 *********************************************************************/
4002
4003 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4004                                             struct auth_serversupplied_info *server_info,
4005                                             struct messaging_context *msg_ctx,
4006                                             const char *name,
4007                                             union spoolss_PrinterInfo **info,
4008                                             uint32_t *count)
4009 {
4010         const char *s = name;
4011
4012         DEBUG(4,("enum_all_printers_info_1_name\n"));
4013
4014         if ((name[0] == '\\') && (name[1] == '\\')) {
4015                 s = name + 2;
4016         }
4017
4018         if (!is_myname_or_ipaddr(s)) {
4019                 return WERR_INVALID_NAME;
4020         }
4021
4022         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4023                                         PRINTER_ENUM_ICON8, info, count);
4024 }
4025
4026 /********************************************************************
4027  enum_all_printers_info_1_network.
4028 *********************************************************************/
4029
4030 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4031                                                struct auth_serversupplied_info *server_info,
4032                                                struct messaging_context *msg_ctx,
4033                                                const char *name,
4034                                                union spoolss_PrinterInfo **info,
4035                                                uint32_t *count)
4036 {
4037         const char *s = name;
4038
4039         DEBUG(4,("enum_all_printers_info_1_network\n"));
4040
4041         /* If we respond to a enum_printers level 1 on our name with flags
4042            set to PRINTER_ENUM_REMOTE with a list of printers then these
4043            printers incorrectly appear in the APW browse list.
4044            Specifically the printers for the server appear at the workgroup
4045            level where all the other servers in the domain are
4046            listed. Windows responds to this call with a
4047            WERR_CAN_NOT_COMPLETE so we should do the same. */
4048
4049         if (name[0] == '\\' && name[1] == '\\') {
4050                  s = name + 2;
4051         }
4052
4053         if (is_myname_or_ipaddr(s)) {
4054                  return WERR_CAN_NOT_COMPLETE;
4055         }
4056
4057         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4058                                         PRINTER_ENUM_NAME, info, count);
4059 }
4060
4061 /********************************************************************
4062  * api_spoolss_enumprinters
4063  *
4064  * called from api_spoolss_enumprinters (see this to understand)
4065  ********************************************************************/
4066
4067 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4068                                        struct auth_serversupplied_info *server_info,
4069                                        struct messaging_context *msg_ctx,
4070                                        union spoolss_PrinterInfo **info,
4071                                        uint32_t *count)
4072 {
4073         DEBUG(4,("enum_all_printers_info_2\n"));
4074
4075         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4076                                             2, 0, info, count);
4077 }
4078
4079 /********************************************************************
4080  * handle enumeration of printers at level 1
4081  ********************************************************************/
4082
4083 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4084                                   struct auth_serversupplied_info *server_info,
4085                                   struct messaging_context *msg_ctx,
4086                                   uint32_t flags,
4087                                   const char *name,
4088                                   union spoolss_PrinterInfo **info,
4089                                   uint32_t *count)
4090 {
4091         /* Not all the flags are equals */
4092
4093         if (flags & PRINTER_ENUM_LOCAL) {
4094                 return enum_all_printers_info_1_local(mem_ctx, server_info,
4095                                                       msg_ctx, info, count);
4096         }
4097
4098         if (flags & PRINTER_ENUM_NAME) {
4099                 return enum_all_printers_info_1_name(mem_ctx, server_info,
4100                                                      msg_ctx, name, info,
4101                                                      count);
4102         }
4103
4104         if (flags & PRINTER_ENUM_NETWORK) {
4105                 return enum_all_printers_info_1_network(mem_ctx, server_info,
4106                                                         msg_ctx, name, info,
4107                                                         count);
4108         }
4109
4110         return WERR_OK; /* NT4sp5 does that */
4111 }
4112
4113 /********************************************************************
4114  * handle enumeration of printers at level 2
4115  ********************************************************************/
4116
4117 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4118                                   struct auth_serversupplied_info *server_info,
4119                                   struct messaging_context *msg_ctx,
4120                                   uint32_t flags,
4121                                   const char *servername,
4122                                   union spoolss_PrinterInfo **info,
4123                                   uint32_t *count)
4124 {
4125         if (flags & PRINTER_ENUM_LOCAL) {
4126                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4127                                                 info, count);
4128         }
4129
4130         if (flags & PRINTER_ENUM_NAME) {
4131                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4132                         return WERR_INVALID_NAME;
4133                 }
4134
4135                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4136                                                 info, count);
4137         }
4138
4139         if (flags & PRINTER_ENUM_REMOTE) {
4140                 return WERR_UNKNOWN_LEVEL;
4141         }
4142
4143         return WERR_OK;
4144 }
4145
4146 /********************************************************************
4147  * handle enumeration of printers at level 4
4148  ********************************************************************/
4149
4150 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4151                                   struct auth_serversupplied_info *server_info,
4152                                   struct messaging_context *msg_ctx,
4153                                   uint32_t flags,
4154                                   const char *servername,
4155                                   union spoolss_PrinterInfo **info,
4156                                   uint32_t *count)
4157 {
4158         DEBUG(4,("enum_all_printers_info_4\n"));
4159
4160         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4161                                             4, flags, info, count);
4162 }
4163
4164
4165 /********************************************************************
4166  * handle enumeration of printers at level 5
4167  ********************************************************************/
4168
4169 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4170                                   struct auth_serversupplied_info *server_info,
4171                                   struct messaging_context *msg_ctx,
4172                                   uint32_t flags,
4173                                   const char *servername,
4174                                   union spoolss_PrinterInfo **info,
4175                                   uint32_t *count)
4176 {
4177         DEBUG(4,("enum_all_printers_info_5\n"));
4178
4179         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4180                                             5, flags, info, count);
4181 }
4182
4183 /****************************************************************
4184  _spoolss_EnumPrinters
4185 ****************************************************************/
4186
4187 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4188                              struct spoolss_EnumPrinters *r)
4189 {
4190         const char *name = NULL;
4191         WERROR result;
4192
4193         /* that's an [in out] buffer */
4194
4195         if (!r->in.buffer && (r->in.offered != 0)) {
4196                 return WERR_INVALID_PARAM;
4197         }
4198
4199         DEBUG(4,("_spoolss_EnumPrinters\n"));
4200
4201         *r->out.needed = 0;
4202         *r->out.count = 0;
4203         *r->out.info = NULL;
4204
4205         /*
4206          * Level 1:
4207          *          flags==PRINTER_ENUM_NAME
4208          *           if name=="" then enumerates all printers
4209          *           if name!="" then enumerate the printer
4210          *          flags==PRINTER_ENUM_REMOTE
4211          *          name is NULL, enumerate printers
4212          * Level 2: name!="" enumerates printers, name can't be NULL
4213          * Level 3: doesn't exist
4214          * Level 4: does a local registry lookup
4215          * Level 5: same as Level 2
4216          */
4217
4218         if (r->in.server) {
4219                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4220                 W_ERROR_HAVE_NO_MEMORY(name);
4221         }
4222
4223         switch (r->in.level) {
4224         case 0:
4225                 result = enumprinters_level0(p->mem_ctx, p->server_info,
4226                                              p->msg_ctx, r->in.flags, name,
4227                                              r->out.info, r->out.count);
4228                 break;
4229         case 1:
4230                 result = enumprinters_level1(p->mem_ctx, p->server_info,
4231                                              p->msg_ctx, r->in.flags, name,
4232                                              r->out.info, r->out.count);
4233                 break;
4234         case 2:
4235                 result = enumprinters_level2(p->mem_ctx, p->server_info,
4236                                              p->msg_ctx, r->in.flags, name,
4237                                              r->out.info, r->out.count);
4238                 break;
4239         case 4:
4240                 result = enumprinters_level4(p->mem_ctx, p->server_info,
4241                                              p->msg_ctx, r->in.flags, name,
4242                                              r->out.info, r->out.count);
4243                 break;
4244         case 5:
4245                 result = enumprinters_level5(p->mem_ctx, p->server_info,
4246                                              p->msg_ctx, r->in.flags, name,
4247                                              r->out.info, r->out.count);
4248                 break;
4249         default:
4250                 return WERR_UNKNOWN_LEVEL;
4251         }
4252
4253         if (!W_ERROR_IS_OK(result)) {
4254                 return result;
4255         }
4256
4257         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4258                                                      spoolss_EnumPrinters, 
4259                                                      *r->out.info, r->in.level,
4260                                                      *r->out.count);
4261         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4262         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4263
4264         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4265 }
4266
4267 /****************************************************************
4268  _spoolss_GetPrinter
4269 ****************************************************************/
4270
4271 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4272                            struct spoolss_GetPrinter *r)
4273 {
4274         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4275         struct spoolss_PrinterInfo2 *info2 = NULL;
4276         WERROR result = WERR_OK;
4277         const char *servername = NULL;
4278         int snum;
4279
4280         /* that's an [in out] buffer */
4281
4282         if (!r->in.buffer && (r->in.offered != 0)) {
4283                 return WERR_INVALID_PARAM;
4284         }
4285
4286         *r->out.needed = 0;
4287
4288         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4289                 return WERR_BADFID;
4290         }
4291
4292         if (Printer != NULL || Printer->servername != NULL) {
4293                 servername = Printer->servername;
4294         }
4295
4296         result = winreg_get_printer(p->mem_ctx,
4297                                     p->server_info,
4298                                     p->msg_ctx,
4299                                     servername,
4300                                     lp_const_servicename(snum),
4301                                     &info2);
4302         if (!W_ERROR_IS_OK(result)) {
4303                 return result;
4304         }
4305
4306         switch (r->in.level) {
4307         case 0:
4308                 result = construct_printer_info0(p->mem_ctx, p->server_info,
4309                                                  p->msg_ctx, info2,
4310                                                  &r->out.info->info0, snum);
4311                 break;
4312         case 1:
4313                 result = construct_printer_info1(p->mem_ctx, info2,
4314                                                  PRINTER_ENUM_ICON8,
4315                                                  &r->out.info->info1, snum);
4316                 break;
4317         case 2:
4318                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4319                                                  &r->out.info->info2, snum);
4320                 break;
4321         case 3:
4322                 result = construct_printer_info3(p->mem_ctx, info2,
4323                                                  &r->out.info->info3, snum);
4324                 break;
4325         case 4:
4326                 result = construct_printer_info4(p->mem_ctx, info2,
4327                                                  &r->out.info->info4, snum);
4328                 break;
4329         case 5:
4330                 result = construct_printer_info5(p->mem_ctx, info2,
4331                                                  &r->out.info->info5, snum);
4332                 break;
4333         case 6:
4334                 result = construct_printer_info6(p->mem_ctx, info2,
4335                                                  &r->out.info->info6, snum);
4336                 break;
4337         case 7:
4338                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4339                                                  Printer,
4340                                                  &r->out.info->info7, snum);
4341                 break;
4342         case 8:
4343                 result = construct_printer_info8(p->mem_ctx, info2,
4344                                                  &r->out.info->info8, snum);
4345                 break;
4346         default:
4347                 result = WERR_UNKNOWN_LEVEL;
4348                 break;
4349         }
4350
4351         if (!W_ERROR_IS_OK(result)) {
4352                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4353                           r->in.level, win_errstr(result)));
4354                 TALLOC_FREE(r->out.info);
4355                 return result;
4356         }
4357
4358         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4359                                                r->out.info, r->in.level);
4360         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4361
4362         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4363 }
4364
4365 /********************************************************************
4366  ********************************************************************/
4367
4368 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4369         do { \
4370                 if (in && strlen(in)) { \
4371                         out = talloc_strdup(mem_ctx, in); \
4372                 } else { \
4373                         out = talloc_strdup(mem_ctx, ""); \
4374                 } \
4375                 W_ERROR_HAVE_NO_MEMORY(out); \
4376         } while (0);
4377
4378 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4379         do { \
4380                 if (in && strlen(in)) { \
4381                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4382                 } else { \
4383                         out = talloc_strdup(mem_ctx, ""); \
4384                 } \
4385                 W_ERROR_HAVE_NO_MEMORY(out); \
4386         } while (0);
4387
4388 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4389                                                   const char **string_array,
4390                                                   const char ***presult,
4391                                                   const char *cservername,
4392                                                   const char *arch,
4393                                                   int version)
4394 {
4395         int i, num_strings = 0;
4396         const char **array = NULL;
4397
4398         if (string_array == NULL) {
4399                 return WERR_INVALID_PARAMETER;;
4400         }
4401
4402         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4403                 const char *str = NULL;
4404
4405                 if (cservername == NULL || arch == NULL) {
4406                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4407                 } else {
4408                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4409                 }
4410
4411                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4412                         TALLOC_FREE(array);
4413                         return WERR_NOMEM;
4414                 }
4415         }
4416
4417         if (i > 0) {
4418                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4419                              &array, &num_strings);
4420         }
4421
4422         if (presult) {
4423                 *presult = array;
4424         }
4425
4426         return WERR_OK;
4427 }
4428
4429 /********************************************************************
4430  * fill a spoolss_DriverInfo1 struct
4431  ********************************************************************/
4432
4433 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4434                                         struct spoolss_DriverInfo1 *r,
4435                                         const struct spoolss_DriverInfo8 *driver,
4436                                         const char *servername)
4437 {
4438         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4439         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4440
4441         return WERR_OK;
4442 }
4443
4444 /********************************************************************
4445  * fill a spoolss_DriverInfo2 struct
4446  ********************************************************************/
4447
4448 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4449                                         struct spoolss_DriverInfo2 *r,
4450                                         const struct spoolss_DriverInfo8 *driver,
4451                                         const char *servername)
4452
4453 {
4454         const char *cservername = canon_servername(servername);
4455
4456         r->version              = driver->version;
4457
4458         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4459         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4460         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4461         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4462
4463         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4464                                driver->architecture,
4465                                driver->version,
4466                                driver->driver_path,
4467                                r->driver_path);
4468
4469         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4470                                driver->architecture,
4471                                driver->version,
4472                                driver->data_file,
4473                                r->data_file);
4474
4475         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4476                                driver->architecture,
4477                                driver->version,
4478                                driver->config_file,
4479                                r->config_file);
4480
4481         return WERR_OK;
4482 }
4483
4484 /********************************************************************
4485  * fill a spoolss_DriverInfo3 struct
4486  ********************************************************************/
4487
4488 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4489                                         struct spoolss_DriverInfo3 *r,
4490                                         const struct spoolss_DriverInfo8 *driver,
4491                                         const char *servername)
4492 {
4493         const char *cservername = canon_servername(servername);
4494
4495         r->version              = driver->version;
4496
4497         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4498         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4499         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4500         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4501
4502         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4503                                driver->architecture,
4504                                driver->version,
4505                                driver->driver_path,
4506                                r->driver_path);
4507
4508         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4509                                driver->architecture,
4510                                driver->version,
4511                                driver->data_file,
4512                                r->data_file);
4513
4514         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4515                                driver->architecture,
4516                                driver->version,
4517                                driver->config_file,
4518                                r->config_file);
4519
4520         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4521                                driver->architecture,
4522                                driver->version,
4523                                driver->help_file,
4524                                r->help_file);
4525
4526         FILL_DRIVER_STRING(mem_ctx,
4527                            driver->monitor_name,
4528                            r->monitor_name);
4529
4530         FILL_DRIVER_STRING(mem_ctx,
4531                            driver->default_datatype,
4532                            r->default_datatype);
4533
4534         return string_array_from_driver_info(mem_ctx,
4535                                              driver->dependent_files,
4536                                              &r->dependent_files,
4537                                              cservername,
4538                                              driver->architecture,
4539                                              driver->version);
4540 }
4541
4542 /********************************************************************
4543  * fill a spoolss_DriverInfo4 struct
4544  ********************************************************************/
4545
4546 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4547                                         struct spoolss_DriverInfo4 *r,
4548                                         const struct spoolss_DriverInfo8 *driver,
4549                                         const char *servername)
4550 {
4551         const char *cservername = canon_servername(servername);
4552         WERROR result;
4553
4554         r->version              = driver->version;
4555
4556         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4557         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4558         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4559         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4560
4561         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4562                                driver->architecture,
4563                                driver->version,
4564                                driver->driver_path,
4565                                r->driver_path);
4566
4567         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4568                                driver->architecture,
4569                                driver->version,
4570                                driver->data_file,
4571                                r->data_file);
4572
4573         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4574                                driver->architecture,
4575                                driver->version,
4576                                driver->config_file,
4577                                r->config_file);
4578
4579         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4580                                driver->architecture,
4581                                driver->version,
4582                                driver->help_file,
4583                                r->help_file);
4584
4585         result = string_array_from_driver_info(mem_ctx,
4586                                                driver->dependent_files,
4587                                                &r->dependent_files,
4588                                                cservername,
4589                                                driver->architecture,
4590                                                driver->version);
4591         if (!W_ERROR_IS_OK(result)) {
4592                 return result;
4593         }
4594
4595         FILL_DRIVER_STRING(mem_ctx,
4596                            driver->monitor_name,
4597                            r->monitor_name);
4598
4599         FILL_DRIVER_STRING(mem_ctx,
4600                            driver->default_datatype,
4601                            r->default_datatype);
4602
4603
4604         result = string_array_from_driver_info(mem_ctx,
4605                                                driver->previous_names,
4606                                                &r->previous_names,
4607                                                NULL, NULL, 0);
4608
4609         return result;
4610 }
4611
4612 /********************************************************************
4613  * fill a spoolss_DriverInfo5 struct
4614  ********************************************************************/
4615
4616 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4617                                         struct spoolss_DriverInfo5 *r,
4618                                         const struct spoolss_DriverInfo8 *driver,
4619                                         const char *servername)
4620 {
4621         const char *cservername = canon_servername(servername);
4622
4623         r->version              = driver->version;
4624
4625         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4626         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4627         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4628         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4629
4630         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4631                                driver->architecture,
4632                                driver->version,
4633                                driver->driver_path,
4634                                r->driver_path);
4635
4636         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4637                                driver->architecture,
4638                                driver->version,
4639                                driver->data_file,
4640                                r->data_file);
4641
4642         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4643                                driver->architecture,
4644                                driver->version,
4645                                driver->config_file,
4646                                r->config_file);
4647
4648         r->driver_attributes    = 0;
4649         r->config_version       = 0;
4650         r->driver_version       = 0;
4651
4652         return WERR_OK;
4653 }
4654 /********************************************************************
4655  * fill a spoolss_DriverInfo6 struct
4656  ********************************************************************/
4657
4658 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4659                                         struct spoolss_DriverInfo6 *r,
4660                                         const struct spoolss_DriverInfo8 *driver,
4661                                         const char *servername)
4662 {
4663         const char *cservername = canon_servername(servername);
4664         WERROR result;
4665
4666         r->version              = driver->version;
4667
4668         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4669         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4670         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4671         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4672
4673         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4674                                driver->architecture,
4675                                driver->version,
4676                                driver->driver_path,
4677                                r->driver_path);
4678
4679         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4680                                driver->architecture,
4681                                driver->version,
4682                                driver->data_file,
4683                                r->data_file);
4684
4685         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4686                                driver->architecture,
4687                                driver->version,
4688                                driver->config_file,
4689                                r->config_file);
4690
4691         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4692                                driver->architecture,
4693                                driver->version,
4694                                driver->help_file,
4695                                r->help_file);
4696
4697         FILL_DRIVER_STRING(mem_ctx,
4698                            driver->monitor_name,
4699                            r->monitor_name);
4700
4701         FILL_DRIVER_STRING(mem_ctx,
4702                            driver->default_datatype,
4703                            r->default_datatype);
4704
4705         result = string_array_from_driver_info(mem_ctx,
4706                                                driver->dependent_files,
4707                                                &r->dependent_files,
4708                                                cservername,
4709                                                driver->architecture,
4710                                                driver->version);
4711         if (!W_ERROR_IS_OK(result)) {
4712                 return result;
4713         }
4714
4715         result = string_array_from_driver_info(mem_ctx,
4716                                                driver->previous_names,
4717                                                &r->previous_names,
4718                                                NULL, NULL, 0);
4719         if (!W_ERROR_IS_OK(result)) {
4720                 return result;
4721         }
4722
4723         r->driver_date          = driver->driver_date;
4724         r->driver_version       = driver->driver_version;
4725
4726         FILL_DRIVER_STRING(mem_ctx,
4727                            driver->manufacturer_name,
4728                            r->manufacturer_name);
4729         FILL_DRIVER_STRING(mem_ctx,
4730                            driver->manufacturer_url,
4731                            r->manufacturer_url);
4732         FILL_DRIVER_STRING(mem_ctx,
4733                            driver->hardware_id,
4734                            r->hardware_id);
4735         FILL_DRIVER_STRING(mem_ctx,
4736                            driver->provider,
4737                            r->provider);
4738
4739         return WERR_OK;
4740 }
4741
4742 /********************************************************************
4743  * fill a spoolss_DriverInfo8 struct
4744  ********************************************************************/
4745
4746 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4747                                         struct spoolss_DriverInfo8 *r,
4748                                         const struct spoolss_DriverInfo8 *driver,
4749                                         const char *servername)
4750 {
4751         const char *cservername = canon_servername(servername);
4752         WERROR result;
4753
4754         r->version              = driver->version;
4755
4756         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4757         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4758         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4759         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4760
4761         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4762                                driver->architecture,
4763                                driver->version,
4764                                driver->driver_path,
4765                                r->driver_path);
4766
4767         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4768                                driver->architecture,
4769                                driver->version,
4770                                driver->data_file,
4771                                r->data_file);
4772
4773         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4774                                driver->architecture,
4775                                driver->version,
4776                                driver->config_file,
4777                                r->config_file);
4778
4779         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4780                                driver->architecture,
4781                                driver->version,
4782                                driver->help_file,
4783                                r->help_file);
4784
4785         FILL_DRIVER_STRING(mem_ctx,
4786                            driver->monitor_name,
4787                            r->monitor_name);
4788
4789         FILL_DRIVER_STRING(mem_ctx,
4790                            driver->default_datatype,
4791                            r->default_datatype);
4792
4793         result = string_array_from_driver_info(mem_ctx,
4794                                                driver->dependent_files,
4795                                                &r->dependent_files,
4796                                                cservername,
4797                                                driver->architecture,
4798                                                driver->version);
4799         if (!W_ERROR_IS_OK(result)) {
4800                 return result;
4801         }
4802
4803         result = string_array_from_driver_info(mem_ctx,
4804                                                driver->previous_names,
4805                                                &r->previous_names,
4806                                                NULL, NULL, 0);
4807         if (!W_ERROR_IS_OK(result)) {
4808                 return result;
4809         }
4810
4811         r->driver_date          = driver->driver_date;
4812         r->driver_version       = driver->driver_version;
4813
4814         FILL_DRIVER_STRING(mem_ctx,
4815                            driver->manufacturer_name,
4816                            r->manufacturer_name);
4817         FILL_DRIVER_STRING(mem_ctx,
4818                            driver->manufacturer_url,
4819                            r->manufacturer_url);
4820         FILL_DRIVER_STRING(mem_ctx,
4821                            driver->hardware_id,
4822                            r->hardware_id);
4823         FILL_DRIVER_STRING(mem_ctx,
4824                            driver->provider,
4825                            r->provider);
4826
4827         FILL_DRIVER_STRING(mem_ctx,
4828                            driver->print_processor,
4829                            r->print_processor);
4830         FILL_DRIVER_STRING(mem_ctx,
4831                            driver->vendor_setup,
4832                            r->vendor_setup);
4833
4834         result = string_array_from_driver_info(mem_ctx,
4835                                                driver->color_profiles,
4836                                                &r->color_profiles,
4837                                                NULL, NULL, 0);
4838         if (!W_ERROR_IS_OK(result)) {
4839                 return result;
4840         }
4841
4842         FILL_DRIVER_STRING(mem_ctx,
4843                            driver->inf_path,
4844                            r->inf_path);
4845
4846         r->printer_driver_attributes    = driver->printer_driver_attributes;
4847
4848         result = string_array_from_driver_info(mem_ctx,
4849                                                driver->core_driver_dependencies,
4850                                                &r->core_driver_dependencies,
4851                                                NULL, NULL, 0);
4852         if (!W_ERROR_IS_OK(result)) {
4853                 return result;
4854         }
4855
4856         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4857         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4858
4859         return WERR_OK;
4860 }
4861
4862 #if 0 /* disabled until marshalling issues are resolved - gd */
4863 /********************************************************************
4864  ********************************************************************/
4865
4866 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4867                                           struct spoolss_DriverFileInfo *r,
4868                                           const char *cservername,
4869                                           const char *file_name,
4870                                           enum spoolss_DriverFileType file_type,
4871                                           uint32_t file_version)
4872 {
4873         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4874                                           cservername, file_name);
4875         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4876         r->file_type    = file_type;
4877         r->file_version = file_version;
4878
4879         return WERR_OK;
4880 }
4881
4882 /********************************************************************
4883  ********************************************************************/
4884
4885 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4886                                                  const struct spoolss_DriverInfo8 *driver,
4887                                                  const char *cservername,
4888                                                  struct spoolss_DriverFileInfo **info_p,
4889                                                  uint32_t *count_p)
4890 {
4891         struct spoolss_DriverFileInfo *info = NULL;
4892         uint32_t count = 0;
4893         WERROR result;
4894         uint32_t i;
4895
4896         *info_p = NULL;
4897         *count_p = 0;
4898
4899         if (strlen(driver->driver_path)) {
4900                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4901                                             struct spoolss_DriverFileInfo,
4902                                             count + 1);
4903                 W_ERROR_HAVE_NO_MEMORY(info);
4904                 result = fill_spoolss_DriverFileInfo(info,
4905                                                      &info[count],
4906                                                      cservername,
4907                                                      driver->driver_path,
4908                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4909                                                      0);
4910                 W_ERROR_NOT_OK_RETURN(result);
4911                 count++;
4912         }
4913
4914         if (strlen(driver->config_file)) {
4915                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4916                                             struct spoolss_DriverFileInfo,
4917                                             count + 1);
4918                 W_ERROR_HAVE_NO_MEMORY(info);
4919                 result = fill_spoolss_DriverFileInfo(info,
4920                                                      &info[count],
4921                                                      cservername,
4922                                                      driver->config_file,
4923                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4924                                                      0);
4925                 W_ERROR_NOT_OK_RETURN(result);
4926                 count++;
4927         }
4928
4929         if (strlen(driver->data_file)) {
4930                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4931                                             struct spoolss_DriverFileInfo,
4932                                             count + 1);
4933                 W_ERROR_HAVE_NO_MEMORY(info);
4934                 result = fill_spoolss_DriverFileInfo(info,
4935                                                      &info[count],
4936                                                      cservername,
4937                                                      driver->data_file,
4938                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4939                                                      0);
4940                 W_ERROR_NOT_OK_RETURN(result);
4941                 count++;
4942         }
4943
4944         if (strlen(driver->help_file)) {
4945                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4946                                             struct spoolss_DriverFileInfo,
4947                                             count + 1);
4948                 W_ERROR_HAVE_NO_MEMORY(info);
4949                 result = fill_spoolss_DriverFileInfo(info,
4950                                                      &info[count],
4951                                                      cservername,
4952                                                      driver->help_file,
4953                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4954                                                      0);
4955                 W_ERROR_NOT_OK_RETURN(result);
4956                 count++;
4957         }
4958
4959         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4960                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4961                                             struct spoolss_DriverFileInfo,
4962                                             count + 1);
4963                 W_ERROR_HAVE_NO_MEMORY(info);
4964                 result = fill_spoolss_DriverFileInfo(info,
4965                                                      &info[count],
4966                                                      cservername,
4967                                                      driver->dependent_files[i],
4968                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4969                                                      0);
4970                 W_ERROR_NOT_OK_RETURN(result);
4971                 count++;
4972         }
4973
4974         *info_p = info;
4975         *count_p = count;
4976
4977         return WERR_OK;
4978 }
4979
4980 /********************************************************************
4981  * fill a spoolss_DriverInfo101 struct
4982  ********************************************************************/
4983
4984 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4985                                           struct spoolss_DriverInfo101 *r,
4986                                           const struct spoolss_DriverInfo8 *driver,
4987                                           const char *servername)
4988 {
4989         const char *cservername = canon_servername(servername);
4990         WERROR result;
4991
4992         r->version              = driver->version;
4993
4994         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4995         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4996         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4997         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4998
4999         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5000                                                     cservername,
5001                                                     &r->file_info,
5002                                                     &r->file_count);
5003         if (!W_ERROR_IS_OK(result)) {
5004                 return result;
5005         }
5006
5007         FILL_DRIVER_STRING(mem_ctx,
5008                            driver->monitor_name,
5009                            r->monitor_name);
5010
5011         FILL_DRIVER_STRING(mem_ctx,
5012                            driver->default_datatype,
5013                            r->default_datatype);
5014
5015         result = string_array_from_driver_info(mem_ctx,
5016                                                driver->previous_names,
5017                                                &r->previous_names,
5018                                                NULL, NULL, 0);
5019         if (!W_ERROR_IS_OK(result)) {
5020                 return result;
5021         }
5022
5023         r->driver_date          = driver->driver_date;
5024         r->driver_version       = driver->driver_version;
5025
5026         FILL_DRIVER_STRING(mem_ctx,
5027                            driver->manufacturer_name,
5028                            r->manufacturer_name);
5029         FILL_DRIVER_STRING(mem_ctx,
5030                            driver->manufacturer_url,
5031                            r->manufacturer_url);
5032         FILL_DRIVER_STRING(mem_ctx,
5033                            driver->hardware_id,
5034                            r->hardware_id);
5035         FILL_DRIVER_STRING(mem_ctx,
5036                            driver->provider,
5037                            r->provider);
5038
5039         return WERR_OK;
5040 }
5041 #endif
5042 /********************************************************************
5043  ********************************************************************/
5044
5045 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5046                                                   struct auth_serversupplied_info *server_info,
5047                                                   struct messaging_context *msg_ctx,
5048                                                   uint32_t level,
5049                                                   union spoolss_DriverInfo *r,
5050                                                   int snum,
5051                                                   const char *servername,
5052                                                   const char *architecture,
5053                                                   uint32_t version)
5054 {
5055         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5056         struct spoolss_DriverInfo8 *driver;
5057         WERROR result;
5058
5059         result = winreg_get_printer(mem_ctx,
5060                                     server_info,
5061                                     msg_ctx,
5062                                     servername,
5063                                     lp_const_servicename(snum),
5064                                     &pinfo2);
5065
5066         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5067                 win_errstr(result)));
5068
5069         if (!W_ERROR_IS_OK(result)) {
5070                 return WERR_INVALID_PRINTER_NAME;
5071         }
5072
5073         result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5074                                    architecture,
5075                                    pinfo2->drivername, version, &driver);
5076
5077         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5078                 win_errstr(result)));
5079
5080         if (!W_ERROR_IS_OK(result)) {
5081                 /*
5082                  * Is this a W2k client ?
5083                  */
5084
5085                 if (version < 3) {
5086                         talloc_free(pinfo2);
5087                         return WERR_UNKNOWN_PRINTER_DRIVER;
5088                 }
5089
5090                 /* Yes - try again with a WinNT driver. */
5091                 version = 2;
5092                 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5093                                            architecture,
5094                                            pinfo2->drivername,
5095                                            version, &driver);
5096                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5097                         win_errstr(result)));
5098                 if (!W_ERROR_IS_OK(result)) {
5099                         talloc_free(pinfo2);
5100                         return WERR_UNKNOWN_PRINTER_DRIVER;
5101                 }
5102         }
5103
5104         switch (level) {
5105         case 1:
5106                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5107                 break;
5108         case 2:
5109                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5110                 break;
5111         case 3:
5112                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5113                 break;
5114         case 4:
5115                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5116                 break;
5117         case 5:
5118                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5119                 break;
5120         case 6:
5121                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5122                 break;
5123         case 8:
5124                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5125                 break;
5126 #if 0 /* disabled until marshalling issues are resolved - gd */
5127         case 101:
5128                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5129                 break;
5130 #endif
5131         default:
5132                 result = WERR_UNKNOWN_LEVEL;
5133                 break;
5134         }
5135
5136         talloc_free(pinfo2);
5137         talloc_free(driver);
5138
5139         return result;
5140 }
5141
5142 /****************************************************************
5143  _spoolss_GetPrinterDriver2
5144 ****************************************************************/
5145
5146 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5147                                   struct spoolss_GetPrinterDriver2 *r)
5148 {
5149         Printer_entry *printer;
5150         WERROR result;
5151
5152         int snum;
5153
5154         /* that's an [in out] buffer */
5155
5156         if (!r->in.buffer && (r->in.offered != 0)) {
5157                 return WERR_INVALID_PARAM;
5158         }
5159
5160         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5161
5162         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5163                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5164                 return WERR_INVALID_PRINTER_NAME;
5165         }
5166
5167         *r->out.needed = 0;
5168         *r->out.server_major_version = 0;
5169         *r->out.server_minor_version = 0;
5170
5171         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5172                 return WERR_BADFID;
5173         }
5174
5175         result = construct_printer_driver_info_level(p->mem_ctx,
5176                                                      p->server_info,
5177                                                      p->msg_ctx,
5178                                                      r->in.level, r->out.info,
5179                                                      snum, printer->servername,
5180                                                      r->in.architecture,
5181                                                      r->in.client_major_version);
5182         if (!W_ERROR_IS_OK(result)) {
5183                 TALLOC_FREE(r->out.info);
5184                 return result;
5185         }
5186
5187         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5188                                                r->out.info, r->in.level);
5189         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5190
5191         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5192 }
5193
5194
5195 /****************************************************************
5196  _spoolss_StartPagePrinter
5197 ****************************************************************/
5198
5199 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5200                                  struct spoolss_StartPagePrinter *r)
5201 {
5202         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5203
5204         if (!Printer) {
5205                 DEBUG(3,("_spoolss_StartPagePrinter: "
5206                         "Error in startpageprinter printer handle\n"));
5207                 return WERR_BADFID;
5208         }
5209
5210         Printer->page_started = true;
5211         return WERR_OK;
5212 }
5213
5214 /****************************************************************
5215  _spoolss_EndPagePrinter
5216 ****************************************************************/
5217
5218 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5219                                struct spoolss_EndPagePrinter *r)
5220 {
5221         int snum;
5222
5223         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5224
5225         if (!Printer) {
5226                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5227                         OUR_HANDLE(r->in.handle)));
5228                 return WERR_BADFID;
5229         }
5230
5231         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5232                 return WERR_BADFID;
5233
5234         Printer->page_started = false;
5235         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5236
5237         return WERR_OK;
5238 }
5239
5240 /****************************************************************
5241  _spoolss_StartDocPrinter
5242 ****************************************************************/
5243
5244 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5245                                 struct spoolss_StartDocPrinter *r)
5246 {
5247         struct spoolss_DocumentInfo1 *info_1;
5248         int snum;
5249         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5250         WERROR werr;
5251
5252         if (!Printer) {
5253                 DEBUG(2,("_spoolss_StartDocPrinter: "
5254                         "Invalid handle (%s:%u:%u)\n",
5255                         OUR_HANDLE(r->in.handle)));
5256                 return WERR_BADFID;
5257         }
5258
5259         if (Printer->jobid) {
5260                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5261                           "StartDocPrinter called twice! "
5262                           "(existing jobid = %d)\n", Printer->jobid));
5263                 return WERR_INVALID_HANDLE;
5264         }
5265
5266         if (r->in.level != 1) {
5267                 return WERR_UNKNOWN_LEVEL;
5268         }
5269
5270         info_1 = r->in.info.info1;
5271
5272         /*
5273          * a nice thing with NT is it doesn't listen to what you tell it.
5274          * when asked to send _only_ RAW datas, it tries to send datas
5275          * in EMF format.
5276          *
5277          * So I add checks like in NT Server ...
5278          */
5279
5280         if (info_1->datatype) {
5281                 if (strcmp(info_1->datatype, "RAW") != 0) {
5282                         *r->out.job_id = 0;
5283                         return WERR_INVALID_DATATYPE;
5284                 }
5285         }
5286
5287         /* get the share number of the printer */
5288         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5289                 return WERR_BADFID;
5290         }
5291
5292         werr = print_job_start(p->server_info, p->msg_ctx, snum,
5293                                 info_1->document_name, info_1->output_file,
5294                                 Printer->devmode, &Printer->jobid);
5295
5296         /* An error occured in print_job_start() so return an appropriate
5297            NT error code. */
5298
5299         if (!W_ERROR_IS_OK(werr)) {
5300                 return werr;
5301         }
5302
5303         Printer->document_started = true;
5304         *r->out.job_id = Printer->jobid;
5305
5306         return WERR_OK;
5307 }
5308
5309 /****************************************************************
5310  _spoolss_EndDocPrinter
5311 ****************************************************************/
5312
5313 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5314                               struct spoolss_EndDocPrinter *r)
5315 {
5316         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5317         NTSTATUS status;
5318         int snum;
5319
5320         if (!Printer) {
5321                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5322                         OUR_HANDLE(r->in.handle)));
5323                 return WERR_BADFID;
5324         }
5325
5326         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5327                 return WERR_BADFID;
5328         }
5329
5330         Printer->document_started = false;
5331         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5332         if (!NT_STATUS_IS_OK(status)) {
5333                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5334                           "print_job_end failed [%s]\n",
5335                           nt_errstr(status)));
5336         }
5337
5338         Printer->jobid = 0;
5339         return ntstatus_to_werror(status);
5340 }
5341
5342 /****************************************************************
5343  _spoolss_WritePrinter
5344 ****************************************************************/
5345
5346 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5347                              struct spoolss_WritePrinter *r)
5348 {
5349         ssize_t buffer_written;
5350         int snum;
5351         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5352
5353         if (!Printer) {
5354                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5355                         OUR_HANDLE(r->in.handle)));
5356                 *r->out.num_written = r->in._data_size;
5357                 return WERR_BADFID;
5358         }
5359
5360         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5361                 return WERR_BADFID;
5362
5363         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5364         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5365                                                    snum, Printer->jobid,
5366                                                    (const char *)r->in.data.data,
5367                                                    (SMB_OFF_T)-1,
5368                                                    (size_t)r->in._data_size);
5369         if (buffer_written == (ssize_t)-1) {
5370                 *r->out.num_written = 0;
5371                 if (errno == ENOSPC)
5372                         return WERR_NO_SPOOL_SPACE;
5373                 else
5374                         return WERR_ACCESS_DENIED;
5375         }
5376
5377         *r->out.num_written = r->in._data_size;
5378
5379         return WERR_OK;
5380 }
5381
5382 /********************************************************************
5383  * api_spoolss_getprinter
5384  * called from the spoolss dispatcher
5385  *
5386  ********************************************************************/
5387
5388 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5389                               struct pipes_struct *p)
5390 {
5391         int snum;
5392         WERROR errcode = WERR_BADFUNC;
5393         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5394
5395         if (!Printer) {
5396                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5397                         OUR_HANDLE(handle)));
5398                 return WERR_BADFID;
5399         }
5400
5401         if (!get_printer_snum(p, handle, &snum, NULL))
5402                 return WERR_BADFID;
5403
5404         switch (command) {
5405         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5406                 errcode = print_queue_pause(p->server_info, p->msg_ctx, snum);
5407                 break;
5408         case SPOOLSS_PRINTER_CONTROL_RESUME:
5409         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5410                 errcode = print_queue_resume(p->server_info, p->msg_ctx, snum);
5411                 break;
5412         case SPOOLSS_PRINTER_CONTROL_PURGE:
5413                 errcode = print_queue_purge(p->server_info, p->msg_ctx, snum);
5414                 break;
5415         default:
5416                 return WERR_UNKNOWN_LEVEL;
5417         }
5418
5419         return errcode;
5420 }
5421
5422
5423 /****************************************************************
5424  _spoolss_AbortPrinter
5425  * From MSDN: "Deletes printer's spool file if printer is configured
5426  * for spooling"
5427 ****************************************************************/
5428
5429 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5430                              struct spoolss_AbortPrinter *r)
5431 {
5432         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5433         int             snum;
5434         WERROR          errcode = WERR_OK;
5435
5436         if (!Printer) {
5437                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5438                         OUR_HANDLE(r->in.handle)));
5439                 return WERR_BADFID;
5440         }
5441
5442         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5443                 return WERR_BADFID;
5444
5445         if (!Printer->document_started) {
5446                 return WERR_SPL_NO_STARTDOC;
5447         }
5448
5449         errcode = print_job_delete(p->server_info, p->msg_ctx, snum,
5450                                    Printer->jobid);
5451
5452         return errcode;
5453 }
5454
5455 /********************************************************************
5456  * called by spoolss_api_setprinter
5457  * when updating a printer description
5458  ********************************************************************/
5459
5460 static WERROR update_printer_sec(struct policy_handle *handle,
5461                                  struct pipes_struct *p,
5462                                  struct sec_desc_buf *secdesc_ctr)
5463 {
5464         struct spoolss_security_descriptor *new_secdesc = NULL;
5465         struct spoolss_security_descriptor *old_secdesc = NULL;
5466         const char *printer;
5467         WERROR result;
5468         int snum;
5469
5470         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5471
5472         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5473                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5474                          OUR_HANDLE(handle)));
5475
5476                 result = WERR_BADFID;
5477                 goto done;
5478         }
5479
5480         if (secdesc_ctr == NULL) {
5481                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5482                 result = WERR_INVALID_PARAM;
5483                 goto done;
5484         }
5485         printer = lp_const_servicename(snum);
5486
5487         /* Check the user has permissions to change the security
5488            descriptor.  By experimentation with two NT machines, the user
5489            requires Full Access to the printer to change security
5490            information. */
5491
5492         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5493                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5494                 result = WERR_ACCESS_DENIED;
5495                 goto done;
5496         }
5497
5498         /* NT seems to like setting the security descriptor even though
5499            nothing may have actually changed. */
5500         result = winreg_get_printer_secdesc(p->mem_ctx,
5501                                             p->server_info,
5502                                             p->msg_ctx,
5503                                             printer,
5504                                             &old_secdesc);
5505         if (!W_ERROR_IS_OK(result)) {
5506                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5507                 result = WERR_BADFID;
5508                 goto done;
5509         }
5510
5511         if (DEBUGLEVEL >= 10) {
5512                 struct security_acl *the_acl;
5513                 int i;
5514
5515                 the_acl = old_secdesc->dacl;
5516                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5517                            printer, the_acl->num_aces));
5518
5519                 for (i = 0; i < the_acl->num_aces; i++) {
5520                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5521                                            &the_acl->aces[i].trustee),
5522                                   the_acl->aces[i].access_mask));
5523                 }
5524
5525                 the_acl = secdesc_ctr->sd->dacl;
5526
5527                 if (the_acl) {
5528                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5529                                    printer, the_acl->num_aces));
5530
5531                         for (i = 0; i < the_acl->num_aces; i++) {
5532                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5533                                                    &the_acl->aces[i].trustee),
5534                                            the_acl->aces[i].access_mask));
5535                         }
5536                 } else {
5537                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5538                 }
5539         }
5540
5541         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5542         if (new_secdesc == NULL) {
5543                 result = WERR_NOMEM;
5544                 goto done;
5545         }
5546
5547         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5548                 result = WERR_OK;
5549                 goto done;
5550         }
5551
5552         result = winreg_set_printer_secdesc(p->mem_ctx,
5553                                             p->server_info,
5554                                             p->msg_ctx,
5555                                             printer,
5556                                             new_secdesc);
5557
5558  done:
5559         return result;
5560 }
5561
5562 /********************************************************************
5563  Canonicalize printer info from a client
5564  ********************************************************************/
5565
5566 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5567                              struct spoolss_SetPrinterInfo2 *info2,
5568                              int snum)
5569 {
5570         fstring printername;
5571         const char *p;
5572
5573         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5574                 "portname=%s drivername=%s comment=%s location=%s\n",
5575                 info2->servername, info2->printername, info2->sharename,
5576                 info2->portname, info2->drivername, info2->comment,
5577                 info2->location));
5578
5579         /* we force some elements to "correct" values */
5580         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5581         if (info2->servername == NULL) {
5582                 return false;
5583         }
5584         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5585         if (info2->sharename == NULL) {
5586                 return false;
5587         }
5588
5589         /* check to see if we allow printername != sharename */
5590         if (lp_force_printername(snum)) {
5591                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5592                                         global_myname(), info2->sharename);
5593         } else {
5594                 /* make sure printername is in \\server\printername format */
5595                 fstrcpy(printername, info2->printername);
5596                 p = printername;
5597                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5598                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5599                                 p++;
5600                 }
5601
5602                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5603                                         global_myname(), p);
5604         }
5605         if (info2->printername == NULL) {
5606                 return false;
5607         }
5608
5609         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5610         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5611
5612         return true;
5613 }
5614
5615 /****************************************************************************
5616 ****************************************************************************/
5617
5618 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5619 {
5620         char *cmd = lp_addport_cmd();
5621         char *command = NULL;
5622         int ret;
5623         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5624         bool is_print_op = false;
5625
5626         if ( !*cmd ) {
5627                 return WERR_ACCESS_DENIED;
5628         }
5629
5630         command = talloc_asprintf(ctx,
5631                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5632         if (!command) {
5633                 return WERR_NOMEM;
5634         }
5635
5636         if ( token )
5637                 is_print_op = user_has_privileges( token, &se_printop );
5638
5639         DEBUG(10,("Running [%s]\n", command));
5640
5641         /********* BEGIN SePrintOperatorPrivilege **********/
5642
5643         if ( is_print_op )
5644                 become_root();
5645
5646         ret = smbrun(command, NULL);
5647
5648         if ( is_print_op )
5649                 unbecome_root();
5650
5651         /********* END SePrintOperatorPrivilege **********/
5652
5653         DEBUGADD(10,("returned [%d]\n", ret));
5654
5655         TALLOC_FREE(command);
5656
5657         if ( ret != 0 ) {
5658                 return WERR_ACCESS_DENIED;
5659         }
5660
5661         return WERR_OK;
5662 }
5663
5664 /****************************************************************************
5665 ****************************************************************************/
5666
5667 static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5668                              struct spoolss_SetPrinterInfo2 *info2,
5669                              const char *remote_machine,
5670                              struct messaging_context *msg_ctx)
5671 {
5672         char *cmd = lp_addprinter_cmd();
5673         char **qlines;
5674         char *command = NULL;
5675         int numlines;
5676         int ret;
5677         int fd;
5678         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5679         bool is_print_op = false;
5680
5681         if (!remote_machine) {
5682                 return false;
5683         }
5684
5685         command = talloc_asprintf(ctx,
5686                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5687                         cmd, info2->printername, info2->sharename,
5688                         info2->portname, info2->drivername,
5689                         info2->location, info2->comment, remote_machine);
5690         if (!command) {
5691                 return false;
5692         }
5693
5694         if ( token )
5695                 is_print_op = user_has_privileges( token, &se_printop );
5696
5697         DEBUG(10,("Running [%s]\n", command));
5698
5699         /********* BEGIN SePrintOperatorPrivilege **********/
5700
5701         if ( is_print_op )
5702                 become_root();
5703
5704         if ( (ret = smbrun(command, &fd)) == 0 ) {
5705                 /* Tell everyone we updated smb.conf. */
5706                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5707         }
5708
5709         if ( is_print_op )
5710                 unbecome_root();
5711
5712         /********* END SePrintOperatorPrivilege **********/
5713
5714         DEBUGADD(10,("returned [%d]\n", ret));
5715
5716         TALLOC_FREE(command);
5717
5718         if ( ret != 0 ) {
5719                 if (fd != -1)
5720                         close(fd);
5721                 return false;
5722         }
5723
5724         /* reload our services immediately */
5725         become_root();
5726         reload_services(msg_ctx, false);
5727         unbecome_root();
5728
5729         numlines = 0;
5730         /* Get lines and convert them back to dos-codepage */
5731         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5732         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5733         close(fd);
5734
5735         /* Set the portname to what the script says the portname should be. */
5736         /* but don't require anything to be return from the script exit a good error code */
5737
5738         if (numlines) {
5739                 /* Set the portname to what the script says the portname should be. */
5740                 info2->portname = talloc_strdup(ctx, qlines[0]);
5741                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5742         }
5743
5744         TALLOC_FREE(qlines);
5745         return true;
5746 }
5747
5748 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5749                                struct auth_serversupplied_info *server_info,
5750                                struct messaging_context *msg_ctx,
5751                                int snum,
5752                                struct spoolss_SetPrinterInfo2 *printer,
5753                                struct spoolss_PrinterInfo2 *old_printer)
5754 {
5755         bool force_update = (old_printer == NULL);
5756         const char *dnsdomname;
5757         const char *longname;
5758         const char *uncname;
5759         const char *spooling;
5760         DATA_BLOB buffer;
5761         WERROR result = WERR_OK;
5762
5763         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5764                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5765                 winreg_set_printer_dataex(mem_ctx,
5766                                           server_info,
5767                                           msg_ctx,
5768                                           printer->sharename,
5769                                           SPOOL_DSSPOOLER_KEY,
5770                                           SPOOL_REG_DRIVERNAME,
5771                                           REG_SZ,
5772                                           buffer.data,
5773                                           buffer.length);
5774
5775                 if (!force_update) {
5776                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5777                                 printer->drivername));
5778
5779                         notify_printer_driver(server_event_context(), msg_ctx,
5780                                               snum, printer->drivername);
5781                 }
5782         }
5783
5784         if (force_update || !strequal(printer->comment, old_printer->comment)) {
5785                 push_reg_sz(mem_ctx, &buffer, printer->comment);
5786                 winreg_set_printer_dataex(mem_ctx,
5787                                           server_info,
5788                                           msg_ctx,
5789                                           printer->sharename,
5790                                           SPOOL_DSSPOOLER_KEY,
5791                                           SPOOL_REG_DESCRIPTION,
5792                                           REG_SZ,
5793                                           buffer.data,
5794                                           buffer.length);
5795
5796                 if (!force_update) {
5797                         notify_printer_comment(server_event_context(), msg_ctx,
5798                                                snum, printer->comment);
5799                 }
5800         }
5801
5802         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5803                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5804                 winreg_set_printer_dataex(mem_ctx,
5805                                           server_info,
5806                                           msg_ctx,
5807                                           printer->sharename,
5808                                           SPOOL_DSSPOOLER_KEY,
5809                                           SPOOL_REG_PRINTSHARENAME,
5810                                           REG_SZ,
5811                                           buffer.data,
5812                                           buffer.length);
5813
5814                 if (!force_update) {
5815                         notify_printer_sharename(server_event_context(),
5816                                                  msg_ctx,
5817                                                  snum, printer->sharename);
5818                 }
5819         }
5820
5821         if (force_update || !strequal(printer->printername, old_printer->printername)) {
5822                 const char *p;
5823
5824                 p = strrchr(printer->printername, '\\' );
5825                 if (p != NULL) {
5826                         p++;
5827                 } else {
5828                         p = printer->printername;
5829                 }
5830
5831                 push_reg_sz(mem_ctx, &buffer, p);
5832                 winreg_set_printer_dataex(mem_ctx,
5833                                           server_info,
5834                                           msg_ctx,
5835                                           printer->sharename,
5836                                           SPOOL_DSSPOOLER_KEY,
5837                                           SPOOL_REG_PRINTERNAME,
5838                                           REG_SZ,
5839                                           buffer.data,
5840                                           buffer.length);
5841
5842                 if (!force_update) {
5843                         notify_printer_printername(server_event_context(),
5844                                                    msg_ctx, snum, p);
5845                 }
5846         }
5847
5848         if (force_update || !strequal(printer->portname, old_printer->portname)) {
5849                 push_reg_sz(mem_ctx, &buffer, printer->portname);
5850                 winreg_set_printer_dataex(mem_ctx,
5851                                           server_info,
5852                                           msg_ctx,
5853                                           printer->sharename,
5854                                           SPOOL_DSSPOOLER_KEY,
5855                                           SPOOL_REG_PORTNAME,
5856                                           REG_SZ,
5857                                           buffer.data,
5858                                           buffer.length);
5859
5860                 if (!force_update) {
5861                         notify_printer_port(server_event_context(),
5862                                             msg_ctx, snum, printer->portname);
5863                 }
5864         }
5865
5866         if (force_update || !strequal(printer->location, old_printer->location)) {
5867                 push_reg_sz(mem_ctx, &buffer, printer->location);
5868                 winreg_set_printer_dataex(mem_ctx,
5869                                           server_info,
5870                                           msg_ctx,
5871                                           printer->sharename,
5872                                           SPOOL_DSSPOOLER_KEY,
5873                                           SPOOL_REG_LOCATION,
5874                                           REG_SZ,
5875                                           buffer.data,
5876                                           buffer.length);
5877
5878                 if (!force_update) {
5879                         notify_printer_location(server_event_context(),
5880                                                 msg_ctx, snum,
5881                                                 printer->location);
5882                 }
5883         }
5884
5885         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
5886                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
5887                 winreg_set_printer_dataex(mem_ctx,
5888                                           server_info,
5889                                           msg_ctx,
5890                                           printer->sharename,
5891                                           SPOOL_DSSPOOLER_KEY,
5892                                           SPOOL_REG_PRINTSEPARATORFILE,
5893                                           REG_SZ,
5894                                           buffer.data,
5895                                           buffer.length);
5896
5897                 if (!force_update) {
5898                         notify_printer_location(server_event_context(),
5899                                                 msg_ctx, snum,
5900                                                 printer->location);
5901                 }
5902         }
5903
5904         if (force_update || printer->starttime != old_printer->starttime) {
5905                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5906                 SIVAL(buffer.data, 0, printer->starttime);
5907                 winreg_set_printer_dataex(mem_ctx,
5908                                           server_info,
5909                                           msg_ctx,
5910                                           printer->sharename,
5911                                           SPOOL_DSSPOOLER_KEY,
5912                                           SPOOL_REG_PRINTSTARTTIME,
5913                                           REG_DWORD,
5914                                           buffer.data,
5915                                           buffer.length);
5916         }
5917
5918         if (force_update || printer->untiltime != old_printer->untiltime) {
5919                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5920                 SIVAL(buffer.data, 0, printer->untiltime);
5921                 winreg_set_printer_dataex(mem_ctx,
5922                                           server_info,
5923                                           msg_ctx,
5924                                           printer->sharename,
5925                                           SPOOL_DSSPOOLER_KEY,
5926                                           SPOOL_REG_PRINTENDTIME,
5927                                           REG_DWORD,
5928                                           buffer.data,
5929                                           buffer.length);
5930         }
5931
5932         if (force_update || printer->priority != old_printer->priority) {
5933                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5934                 SIVAL(buffer.data, 0, printer->priority);
5935                 winreg_set_printer_dataex(mem_ctx,
5936                                           server_info,
5937                                           msg_ctx,
5938                                           printer->sharename,
5939                                           SPOOL_DSSPOOLER_KEY,
5940                                           SPOOL_REG_PRIORITY,
5941                                           REG_DWORD,
5942                                           buffer.data,
5943                                           buffer.length);
5944         }
5945
5946         if (force_update || printer->attributes != old_printer->attributes) {
5947                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5948                 SIVAL(buffer.data, 0, (printer->attributes &
5949                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
5950                 winreg_set_printer_dataex(mem_ctx,
5951                                           server_info,
5952                                           msg_ctx,
5953                                           printer->sharename,
5954                                           SPOOL_DSSPOOLER_KEY,
5955                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
5956                                           REG_DWORD,
5957                                           buffer.data,
5958                                           buffer.length);
5959
5960                 switch (printer->attributes & 0x3) {
5961                         case 0:
5962                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
5963                                 break;
5964                         case 1:
5965                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
5966                                 break;
5967                         case 2:
5968                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
5969                                 break;
5970                         default:
5971                                 spooling = "unknown";
5972                 }
5973                 push_reg_sz(mem_ctx, &buffer, spooling);
5974                 winreg_set_printer_dataex(mem_ctx,
5975                                           server_info,
5976                                           msg_ctx,
5977                                           printer->sharename,
5978                                           SPOOL_DSSPOOLER_KEY,
5979                                           SPOOL_REG_PRINTSPOOLING,
5980                                           REG_SZ,
5981                                           buffer.data,
5982                                           buffer.length);
5983         }
5984
5985         push_reg_sz(mem_ctx, &buffer, global_myname());
5986         winreg_set_printer_dataex(mem_ctx,
5987                                   server_info,
5988                                   msg_ctx,
5989                                   printer->sharename,
5990                                   SPOOL_DSSPOOLER_KEY,
5991                                   SPOOL_REG_SHORTSERVERNAME,
5992                                   REG_SZ,
5993                                   buffer.data,
5994                                   buffer.length);
5995
5996         dnsdomname = get_mydnsfullname();
5997         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
5998                 longname = talloc_strdup(mem_ctx, dnsdomname);
5999         } else {
6000                 longname = talloc_strdup(mem_ctx, global_myname());
6001         }
6002         if (longname == NULL) {
6003                 result = WERR_NOMEM;
6004                 goto done;
6005         }
6006
6007         push_reg_sz(mem_ctx, &buffer, longname);
6008         winreg_set_printer_dataex(mem_ctx,
6009                                   server_info,
6010                                   msg_ctx,
6011                                   printer->sharename,
6012                                   SPOOL_DSSPOOLER_KEY,
6013                                   SPOOL_REG_SERVERNAME,
6014                                   REG_SZ,
6015                                   buffer.data,
6016                                   buffer.length);
6017
6018         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6019                                   global_myname(), printer->sharename);
6020         push_reg_sz(mem_ctx, &buffer, uncname);
6021         winreg_set_printer_dataex(mem_ctx,
6022                                   server_info,
6023                                   msg_ctx,
6024                                   printer->sharename,
6025                                   SPOOL_DSSPOOLER_KEY,
6026                                   SPOOL_REG_UNCNAME,
6027                                   REG_SZ,
6028                                   buffer.data,
6029                                   buffer.length);
6030
6031 done:
6032         return result;
6033 }
6034
6035 /********************************************************************
6036  * Called by spoolss_api_setprinter
6037  * when updating a printer description.
6038  ********************************************************************/
6039
6040 static WERROR update_printer(struct pipes_struct *p,
6041                              struct policy_handle *handle,
6042                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6043                              struct spoolss_DeviceMode *devmode)
6044 {
6045         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6046         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6047         struct spoolss_PrinterInfo2 *old_printer;
6048         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6049         const char *servername = NULL;
6050         int snum;
6051         WERROR result = WERR_OK;
6052         TALLOC_CTX *tmp_ctx;
6053
6054         DEBUG(8,("update_printer\n"));
6055
6056         tmp_ctx = talloc_new(p->mem_ctx);
6057         if (tmp_ctx == NULL) {
6058                 return WERR_NOMEM;
6059         }
6060
6061         if (!Printer) {
6062                 result = WERR_BADFID;
6063                 goto done;
6064         }
6065
6066         if (!get_printer_snum(p, handle, &snum, NULL)) {
6067                 result = WERR_BADFID;
6068                 goto done;
6069         }
6070
6071         if (Printer != NULL || Printer->servername != NULL) {
6072                 servername = Printer->servername;
6073         }
6074
6075         result = winreg_get_printer(tmp_ctx,
6076                                     p->server_info,
6077                                     p->msg_ctx,
6078                                     servername,
6079                                     lp_const_servicename(snum),
6080                                     &old_printer);
6081         if (!W_ERROR_IS_OK(result)) {
6082                 result = WERR_BADFID;
6083                 goto done;
6084         }
6085
6086         /* Do sanity check on the requested changes for Samba */
6087         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6088                 result = WERR_INVALID_PARAM;
6089                 goto done;
6090         }
6091
6092         /* FIXME!!! If the driver has changed we really should verify that
6093            it is installed before doing much else   --jerry */
6094
6095         /* Check calling user has permission to update printer description */
6096         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6097                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6098                 result = WERR_ACCESS_DENIED;
6099                 goto done;
6100         }
6101
6102         /* Call addprinter hook */
6103         /* Check changes to see if this is really needed */
6104
6105         if (*lp_addprinter_cmd() &&
6106                         (!strequal(printer->drivername, old_printer->drivername) ||
6107                          !strequal(printer->comment, old_printer->comment) ||
6108                          !strequal(printer->portname, old_printer->portname) ||
6109                          !strequal(printer->location, old_printer->location)) )
6110         {
6111                 /* add_printer_hook() will call reload_services() */
6112                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6113                                       printer, p->client_address,
6114                                       p->msg_ctx)) {
6115                         result = WERR_ACCESS_DENIED;
6116                         goto done;
6117                 }
6118         }
6119
6120         update_dsspooler(tmp_ctx,
6121                          p->server_info,
6122                          p->msg_ctx,
6123                          snum,
6124                          printer,
6125                          old_printer);
6126
6127         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6128
6129         if (devmode == NULL) {
6130                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6131         }
6132         result = winreg_update_printer(tmp_ctx,
6133                                        p->server_info,
6134                                        p->msg_ctx,
6135                                        printer->sharename,
6136                                        printer_mask,
6137                                        printer,
6138                                        devmode,
6139                                        NULL);
6140
6141 done:
6142         talloc_free(tmp_ctx);
6143
6144         return result;
6145 }
6146
6147 /****************************************************************************
6148 ****************************************************************************/
6149 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6150                                            struct policy_handle *handle,
6151                                            struct spoolss_SetPrinterInfo7 *info7)
6152 {
6153 #ifdef HAVE_ADS
6154         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6155         WERROR result;
6156         int snum;
6157         Printer_entry *Printer;
6158
6159         if ( lp_security() != SEC_ADS ) {
6160                 return WERR_UNKNOWN_LEVEL;
6161         }
6162
6163         Printer = find_printer_index_by_hnd(p, handle);
6164
6165         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6166
6167         if (!Printer)
6168                 return WERR_BADFID;
6169
6170         if (!get_printer_snum(p, handle, &snum, NULL))
6171                 return WERR_BADFID;
6172
6173         result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
6174                                     Printer->servername,
6175                                     lp_servicename(snum), &pinfo2);
6176         if (!W_ERROR_IS_OK(result)) {
6177                 return WERR_BADFID;
6178         }
6179
6180         nt_printer_publish(pinfo2, p->server_info, p->msg_ctx, pinfo2,
6181                            info7->action);
6182
6183         TALLOC_FREE(pinfo2);
6184         return WERR_OK;
6185 #else
6186         return WERR_UNKNOWN_LEVEL;
6187 #endif
6188 }
6189
6190 /********************************************************************
6191  ********************************************************************/
6192
6193 static WERROR update_printer_devmode(struct pipes_struct *p,
6194                                      struct policy_handle *handle,
6195                                      struct spoolss_DeviceMode *devmode)
6196 {
6197         int snum;
6198         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6199         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6200
6201         DEBUG(8,("update_printer_devmode\n"));
6202
6203         if (!Printer) {
6204                 return WERR_BADFID;
6205         }
6206
6207         if (!get_printer_snum(p, handle, &snum, NULL)) {
6208                 return WERR_BADFID;
6209         }
6210
6211         /* Check calling user has permission to update printer description */
6212         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6213                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6214                 return WERR_ACCESS_DENIED;
6215         }
6216
6217         return winreg_update_printer(p->mem_ctx,
6218                                      p->server_info,
6219                                      p->msg_ctx,
6220                                      lp_const_servicename(snum),
6221                                      info2_mask,
6222                                      NULL,
6223                                      devmode,
6224                                      NULL);
6225 }
6226
6227
6228 /****************************************************************
6229  _spoolss_SetPrinter
6230 ****************************************************************/
6231
6232 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6233                            struct spoolss_SetPrinter *r)
6234 {
6235         WERROR result;
6236
6237         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6238
6239         if (!Printer) {
6240                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6241                         OUR_HANDLE(r->in.handle)));
6242                 return WERR_BADFID;
6243         }
6244
6245         /* check the level */
6246         switch (r->in.info_ctr->level) {
6247                 case 0:
6248                         return control_printer(r->in.handle, r->in.command, p);
6249                 case 2:
6250                         result = update_printer(p, r->in.handle,
6251                                                 r->in.info_ctr,
6252                                                 r->in.devmode_ctr->devmode);
6253                         if (!W_ERROR_IS_OK(result))
6254                                 return result;
6255                         if (r->in.secdesc_ctr->sd)
6256                                 result = update_printer_sec(r->in.handle, p,
6257                                                             r->in.secdesc_ctr);
6258                         return result;
6259                 case 3:
6260                         return update_printer_sec(r->in.handle, p,
6261                                                   r->in.secdesc_ctr);
6262                 case 7:
6263                         return publish_or_unpublish_printer(p, r->in.handle,
6264                                                             r->in.info_ctr->info.info7);
6265                 case 8:
6266                         return update_printer_devmode(p, r->in.handle,
6267                                                       r->in.devmode_ctr->devmode);
6268                 default:
6269                         return WERR_UNKNOWN_LEVEL;
6270         }
6271 }
6272
6273 /****************************************************************
6274  _spoolss_FindClosePrinterNotify
6275 ****************************************************************/
6276
6277 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6278                                        struct spoolss_FindClosePrinterNotify *r)
6279 {
6280         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6281
6282         if (!Printer) {
6283                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6284                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6285                 return WERR_BADFID;
6286         }
6287
6288         if (Printer->notify.client_connected == true) {
6289                 int snum = -1;
6290
6291                 if ( Printer->printer_type == SPLHND_SERVER)
6292                         snum = -1;
6293                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6294                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6295                         return WERR_BADFID;
6296
6297                 srv_spoolss_replycloseprinter(
6298                         snum, &Printer->notify.client_hnd, p->msg_ctx);
6299         }
6300
6301         Printer->notify.flags=0;
6302         Printer->notify.options=0;
6303         Printer->notify.localmachine[0]='\0';
6304         Printer->notify.printerlocal=0;
6305         TALLOC_FREE(Printer->notify.option);
6306         Printer->notify.client_connected = false;
6307
6308         return WERR_OK;
6309 }
6310
6311 /****************************************************************
6312  _spoolss_AddJob
6313 ****************************************************************/
6314
6315 WERROR _spoolss_AddJob(struct pipes_struct *p,
6316                        struct spoolss_AddJob *r)
6317 {
6318         if (!r->in.buffer && (r->in.offered != 0)) {
6319                 return WERR_INVALID_PARAM;
6320         }
6321
6322         /* this is what a NT server returns for AddJob. AddJob must fail on
6323          * non-local printers */
6324
6325         if (r->in.level != 1) {
6326                 return WERR_UNKNOWN_LEVEL;
6327         }
6328
6329         return WERR_INVALID_PARAM;
6330 }
6331
6332 /****************************************************************************
6333 fill_job_info1
6334 ****************************************************************************/
6335
6336 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6337                              struct spoolss_JobInfo1 *r,
6338                              const print_queue_struct *queue,
6339                              int position, int snum,
6340                              struct spoolss_PrinterInfo2 *pinfo2)
6341 {
6342         struct tm *t;
6343
6344         t = gmtime(&queue->time);
6345
6346         r->job_id               = queue->job;
6347
6348         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6349         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6350         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6351         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6352         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6353         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6354         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6355         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6356         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6357         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6358         r->text_status          = talloc_strdup(mem_ctx, "");
6359         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6360
6361         r->status               = nt_printj_status(queue->status);
6362         r->priority             = queue->priority;
6363         r->position             = position;
6364         r->total_pages          = queue->page_count;
6365         r->pages_printed        = 0; /* ??? */
6366
6367         init_systemtime(&r->submitted, t);
6368
6369         return WERR_OK;
6370 }
6371
6372 /****************************************************************************
6373 fill_job_info2
6374 ****************************************************************************/
6375
6376 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6377                              struct spoolss_JobInfo2 *r,
6378                              const print_queue_struct *queue,
6379                              int position, int snum,
6380                              struct spoolss_PrinterInfo2 *pinfo2,
6381                              struct spoolss_DeviceMode *devmode)
6382 {
6383         struct tm *t;
6384
6385         t = gmtime(&queue->time);
6386
6387         r->job_id               = queue->job;
6388
6389         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6390         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6391         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6392         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6393         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6394         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6395         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6396         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6397         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6398         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6399         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6400         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6401         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6402         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6403         r->parameters           = talloc_strdup(mem_ctx, "");
6404         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6405         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6406         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6407
6408         r->devmode              = devmode;
6409
6410         r->text_status          = talloc_strdup(mem_ctx, "");
6411         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6412
6413         r->secdesc              = NULL;
6414
6415         r->status               = nt_printj_status(queue->status);
6416         r->priority             = queue->priority;
6417         r->position             = position;
6418         r->start_time           = 0;
6419         r->until_time           = 0;
6420         r->total_pages          = queue->page_count;
6421         r->size                 = queue->size;
6422         init_systemtime(&r->submitted, t);
6423         r->time                 = 0;
6424         r->pages_printed        = 0; /* ??? */
6425
6426         return WERR_OK;
6427 }
6428
6429 /****************************************************************************
6430 fill_job_info3
6431 ****************************************************************************/
6432
6433 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6434                              struct spoolss_JobInfo3 *r,
6435                              const print_queue_struct *queue,
6436                              const print_queue_struct *next_queue,
6437                              int position, int snum,
6438                              struct spoolss_PrinterInfo2 *pinfo2)
6439 {
6440         r->job_id               = queue->job;
6441         r->next_job_id          = 0;
6442         if (next_queue) {
6443                 r->next_job_id  = next_queue->job;
6444         }
6445         r->reserved             = 0;
6446
6447         return WERR_OK;
6448 }
6449
6450 /****************************************************************************
6451  Enumjobs at level 1.
6452 ****************************************************************************/
6453
6454 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6455                               const print_queue_struct *queue,
6456                               uint32_t num_queues, int snum,
6457                               struct spoolss_PrinterInfo2 *pinfo2,
6458                               union spoolss_JobInfo **info_p,
6459                               uint32_t *count)
6460 {
6461         union spoolss_JobInfo *info;
6462         int i;
6463         WERROR result = WERR_OK;
6464
6465         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6466         W_ERROR_HAVE_NO_MEMORY(info);
6467
6468         *count = num_queues;
6469
6470         for (i=0; i<*count; i++) {
6471                 result = fill_job_info1(info,
6472                                         &info[i].info1,
6473                                         &queue[i],
6474                                         i,
6475                                         snum,
6476                                         pinfo2);
6477                 if (!W_ERROR_IS_OK(result)) {
6478                         goto out;
6479                 }
6480         }
6481
6482  out:
6483         if (!W_ERROR_IS_OK(result)) {
6484                 TALLOC_FREE(info);
6485                 *count = 0;
6486                 return result;
6487         }
6488
6489         *info_p = info;
6490
6491         return WERR_OK;
6492 }
6493
6494 /****************************************************************************
6495  Enumjobs at level 2.
6496 ****************************************************************************/
6497
6498 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6499                               const print_queue_struct *queue,
6500                               uint32_t num_queues, int snum,
6501                               struct spoolss_PrinterInfo2 *pinfo2,
6502                               union spoolss_JobInfo **info_p,
6503                               uint32_t *count)
6504 {
6505         union spoolss_JobInfo *info;
6506         int i;
6507         WERROR result = WERR_OK;
6508
6509         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6510         W_ERROR_HAVE_NO_MEMORY(info);
6511
6512         *count = num_queues;
6513
6514         for (i=0; i<*count; i++) {
6515                 struct spoolss_DeviceMode *devmode;
6516
6517                 result = spoolss_create_default_devmode(info,
6518                                                         pinfo2->printername,
6519                                                         &devmode);
6520                 if (!W_ERROR_IS_OK(result)) {
6521                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6522                         goto out;
6523                 }
6524
6525                 result = fill_job_info2(info,
6526                                         &info[i].info2,
6527                                         &queue[i],
6528                                         i,
6529                                         snum,
6530                                         pinfo2,
6531                                         devmode);
6532                 if (!W_ERROR_IS_OK(result)) {
6533                         goto out;
6534                 }
6535         }
6536
6537  out:
6538         if (!W_ERROR_IS_OK(result)) {
6539                 TALLOC_FREE(info);
6540                 *count = 0;
6541                 return result;
6542         }
6543
6544         *info_p = info;
6545
6546         return WERR_OK;
6547 }
6548
6549 /****************************************************************************
6550  Enumjobs at level 3.
6551 ****************************************************************************/
6552
6553 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6554                               const print_queue_struct *queue,
6555                               uint32_t num_queues, int snum,
6556                               struct spoolss_PrinterInfo2 *pinfo2,
6557                               union spoolss_JobInfo **info_p,
6558                               uint32_t *count)
6559 {
6560         union spoolss_JobInfo *info;
6561         int i;
6562         WERROR result = WERR_OK;
6563
6564         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6565         W_ERROR_HAVE_NO_MEMORY(info);
6566
6567         *count = num_queues;
6568
6569         for (i=0; i<*count; i++) {
6570                 const print_queue_struct *next_queue = NULL;
6571
6572                 if (i+1 < *count) {
6573                         next_queue = &queue[i+1];
6574                 }
6575
6576                 result = fill_job_info3(info,
6577                                         &info[i].info3,
6578                                         &queue[i],
6579                                         next_queue,
6580                                         i,
6581                                         snum,
6582                                         pinfo2);
6583                 if (!W_ERROR_IS_OK(result)) {
6584                         goto out;
6585                 }
6586         }
6587
6588  out:
6589         if (!W_ERROR_IS_OK(result)) {
6590                 TALLOC_FREE(info);
6591                 *count = 0;
6592                 return result;
6593         }
6594
6595         *info_p = info;
6596
6597         return WERR_OK;
6598 }
6599
6600 /****************************************************************
6601  _spoolss_EnumJobs
6602 ****************************************************************/
6603
6604 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6605                          struct spoolss_EnumJobs *r)
6606 {
6607         WERROR result;
6608         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6609         int snum;
6610         print_status_struct prt_status;
6611         print_queue_struct *queue = NULL;
6612         uint32_t count;
6613
6614         /* that's an [in out] buffer */
6615
6616         if (!r->in.buffer && (r->in.offered != 0)) {
6617                 return WERR_INVALID_PARAM;
6618         }
6619
6620         DEBUG(4,("_spoolss_EnumJobs\n"));
6621
6622         *r->out.needed = 0;
6623         *r->out.count = 0;
6624         *r->out.info = NULL;
6625
6626         /* lookup the printer snum and tdb entry */
6627
6628         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6629                 return WERR_BADFID;
6630         }
6631
6632         result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
6633                                     NULL, lp_servicename(snum), &pinfo2);
6634         if (!W_ERROR_IS_OK(result)) {
6635                 return result;
6636         }
6637
6638         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
6639         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6640                 count, prt_status.status, prt_status.message));
6641
6642         if (count == 0) {
6643                 SAFE_FREE(queue);
6644                 TALLOC_FREE(pinfo2);
6645                 return WERR_OK;
6646         }
6647
6648         switch (r->in.level) {
6649         case 1:
6650                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6651                                          pinfo2, r->out.info, r->out.count);
6652                 break;
6653         case 2:
6654                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6655                                          pinfo2, r->out.info, r->out.count);
6656                 break;
6657         case 3:
6658                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6659                                          pinfo2, r->out.info, r->out.count);
6660                 break;
6661         default:
6662                 result = WERR_UNKNOWN_LEVEL;
6663                 break;
6664         }
6665
6666         SAFE_FREE(queue);
6667         TALLOC_FREE(pinfo2);
6668
6669         if (!W_ERROR_IS_OK(result)) {
6670                 return result;
6671         }
6672
6673         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6674                                                      spoolss_EnumJobs, 
6675                                                      *r->out.info, r->in.level,
6676                                                      *r->out.count);
6677         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6678         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6679
6680         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6681 }
6682
6683 /****************************************************************
6684  _spoolss_ScheduleJob
6685 ****************************************************************/
6686
6687 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
6688                             struct spoolss_ScheduleJob *r)
6689 {
6690         return WERR_OK;
6691 }
6692
6693 /****************************************************************
6694 ****************************************************************/
6695
6696 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6697                                const char *printer_name,
6698                                uint32_t job_id,
6699                                struct spoolss_SetJobInfo1 *r)
6700 {
6701         char *old_doc_name;
6702
6703         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6704                 return WERR_BADFID;
6705         }
6706
6707         if (strequal(old_doc_name, r->document_name)) {
6708                 return WERR_OK;
6709         }
6710
6711         if (!print_job_set_name(server_event_context(),
6712                                 server_messaging_context(),
6713                                 printer_name, job_id, r->document_name)) {
6714                 return WERR_BADFID;
6715         }
6716
6717         return WERR_OK;
6718 }
6719
6720 /****************************************************************
6721  _spoolss_SetJob
6722 ****************************************************************/
6723
6724 WERROR _spoolss_SetJob(struct pipes_struct *p,
6725                        struct spoolss_SetJob *r)
6726 {
6727         int snum;
6728         WERROR errcode = WERR_BADFUNC;
6729
6730         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6731                 return WERR_BADFID;
6732         }
6733
6734         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6735                 return WERR_INVALID_PRINTER_NAME;
6736         }
6737
6738         switch (r->in.command) {
6739         case SPOOLSS_JOB_CONTROL_CANCEL:
6740         case SPOOLSS_JOB_CONTROL_DELETE:
6741                 errcode = print_job_delete(p->server_info, p->msg_ctx,
6742                                            snum, r->in.job_id);
6743                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6744                         errcode = WERR_OK;
6745                 }
6746                 break;
6747         case SPOOLSS_JOB_CONTROL_PAUSE:
6748                 if (print_job_pause(p->server_info, p->msg_ctx,
6749                                     snum, r->in.job_id, &errcode)) {
6750                         errcode = WERR_OK;
6751                 }
6752                 break;
6753         case SPOOLSS_JOB_CONTROL_RESTART:
6754         case SPOOLSS_JOB_CONTROL_RESUME:
6755                 if (print_job_resume(p->server_info, p->msg_ctx,
6756                                      snum, r->in.job_id, &errcode)) {
6757                         errcode = WERR_OK;
6758                 }
6759                 break;
6760         case 0:
6761                 errcode = WERR_OK;
6762                 break;
6763         default:
6764                 return WERR_UNKNOWN_LEVEL;
6765         }
6766
6767         if (!W_ERROR_IS_OK(errcode)) {
6768                 return errcode;
6769         }
6770
6771         if (r->in.ctr == NULL) {
6772                 return errcode;
6773         }
6774
6775         switch (r->in.ctr->level) {
6776         case 1:
6777                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6778                                            r->in.job_id,
6779                                            r->in.ctr->info.info1);
6780                 break;
6781         case 2:
6782         case 3:
6783         case 4:
6784         default:
6785                 return WERR_UNKNOWN_LEVEL;
6786         }
6787
6788         return errcode;
6789 }
6790
6791 /****************************************************************************
6792  Enumerates all printer drivers by level and architecture.
6793 ****************************************************************************/
6794
6795 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6796                                                        struct auth_serversupplied_info *server_info,
6797                                                        struct messaging_context *msg_ctx,
6798                                                        const char *servername,
6799                                                        const char *architecture,
6800                                                        uint32_t level,
6801                                                        union spoolss_DriverInfo **info_p,
6802                                                        uint32_t *count_p)
6803 {
6804         int i;
6805         uint32_t version;
6806         struct spoolss_DriverInfo8 *driver;
6807         union spoolss_DriverInfo *info = NULL;
6808         uint32_t count = 0;
6809         WERROR result = WERR_OK;
6810         uint32_t num_drivers;
6811         const char **drivers;
6812
6813         *count_p = 0;
6814         *info_p = NULL;
6815
6816         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6817                 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
6818                                                 architecture, version,
6819                                                 &num_drivers, &drivers);
6820                 if (!W_ERROR_IS_OK(result)) {
6821                         goto out;
6822                 }
6823                 DEBUG(4, ("we have:[%d] drivers in environment"
6824                           " [%s] and version [%d]\n",
6825                           num_drivers, architecture, version));
6826
6827                 if (num_drivers != 0) {
6828                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6829                                                     union spoolss_DriverInfo,
6830                                                     count + num_drivers);
6831                         if (!info) {
6832                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6833                                         "failed to enlarge driver info buffer!\n"));
6834                                 result = WERR_NOMEM;
6835                                 goto out;
6836                         }
6837                 }
6838
6839                 for (i = 0; i < num_drivers; i++) {
6840                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6841
6842                         result = winreg_get_driver(mem_ctx, server_info,
6843                                                    msg_ctx,
6844                                                    architecture, drivers[i],
6845                                                    version, &driver);
6846                         if (!W_ERROR_IS_OK(result)) {
6847                                 goto out;
6848                         }
6849
6850                         switch (level) {
6851                         case 1:
6852                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6853                                                                    driver, servername);
6854                                 break;
6855                         case 2:
6856                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6857                                                                    driver, servername);
6858                                 break;
6859                         case 3:
6860                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6861                                                                    driver, servername);
6862                                 break;
6863                         case 4:
6864                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6865                                                                    driver, servername);
6866                                 break;
6867                         case 5:
6868                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6869                                                                    driver, servername);
6870                                 break;
6871                         case 6:
6872                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6873                                                                    driver, servername);
6874                                 break;
6875                         case 8:
6876                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6877                                                                    driver, servername);
6878                                 break;
6879                         default:
6880                                 result = WERR_UNKNOWN_LEVEL;
6881                                 break;
6882                         }
6883
6884                         TALLOC_FREE(driver);
6885
6886                         if (!W_ERROR_IS_OK(result)) {
6887                                 goto out;
6888                         }
6889                 }
6890
6891                 count += num_drivers;
6892                 TALLOC_FREE(drivers);
6893         }
6894
6895  out:
6896         TALLOC_FREE(drivers);
6897
6898         if (!W_ERROR_IS_OK(result)) {
6899                 TALLOC_FREE(info);
6900                 return result;
6901         }
6902
6903         *info_p = info;
6904         *count_p = count;
6905
6906         return WERR_OK;
6907 }
6908
6909 /****************************************************************************
6910  Enumerates all printer drivers by level.
6911 ****************************************************************************/
6912
6913 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6914                                        struct auth_serversupplied_info *server_info,
6915                                        struct messaging_context *msg_ctx,
6916                                        const char *servername,
6917                                        const char *architecture,
6918                                        uint32_t level,
6919                                        union spoolss_DriverInfo **info_p,
6920                                        uint32_t *count_p)
6921 {
6922         uint32_t a,i;
6923         WERROR result = WERR_OK;
6924
6925         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6926
6927                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6928
6929                         union spoolss_DriverInfo *info = NULL;
6930                         uint32_t count = 0;
6931
6932                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6933                                                                           server_info,
6934                                                                           msg_ctx,
6935                                                                           servername,
6936                                                                           archi_table[a].long_archi,
6937                                                                           level,
6938                                                                           &info,
6939                                                                           &count);
6940                         if (!W_ERROR_IS_OK(result)) {
6941                                 continue;
6942                         }
6943
6944                         for (i=0; i < count; i++) {
6945                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6946                                              info[i], info_p, count_p);
6947                         }
6948                 }
6949
6950                 return result;
6951         }
6952
6953         return enumprinterdrivers_level_by_architecture(mem_ctx,
6954                                                         server_info,
6955                                                         msg_ctx,
6956                                                         servername,
6957                                                         architecture,
6958                                                         level,
6959                                                         info_p,
6960                                                         count_p);
6961 }
6962
6963 /****************************************************************
6964  _spoolss_EnumPrinterDrivers
6965 ****************************************************************/
6966
6967 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
6968                                    struct spoolss_EnumPrinterDrivers *r)
6969 {
6970         const char *cservername;
6971         WERROR result;
6972
6973         /* that's an [in out] buffer */
6974
6975         if (!r->in.buffer && (r->in.offered != 0)) {
6976                 return WERR_INVALID_PARAM;
6977         }
6978
6979         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6980
6981         *r->out.needed = 0;
6982         *r->out.count = 0;
6983         *r->out.info = NULL;
6984
6985         cservername = canon_servername(r->in.server);
6986
6987         if (!is_myname_or_ipaddr(cservername)) {
6988                 return WERR_UNKNOWN_PRINTER_DRIVER;
6989         }
6990
6991         result = enumprinterdrivers_level(p->mem_ctx,
6992                                           p->server_info,
6993                                           p->msg_ctx,
6994                                           cservername,
6995                                           r->in.environment,
6996                                           r->in.level,
6997                                           r->out.info,
6998                                           r->out.count);
6999         if (!W_ERROR_IS_OK(result)) {
7000                 return result;
7001         }
7002
7003         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7004                                                      spoolss_EnumPrinterDrivers, 
7005                                                      *r->out.info, r->in.level,
7006                                                      *r->out.count);
7007         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7008         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7009
7010         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7011 }
7012
7013 /****************************************************************
7014  _spoolss_EnumForms
7015 ****************************************************************/
7016
7017 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7018                           struct spoolss_EnumForms *r)
7019 {
7020         WERROR result;
7021
7022         *r->out.count = 0;
7023         *r->out.needed = 0;
7024         *r->out.info = NULL;
7025
7026         /* that's an [in out] buffer */
7027
7028         if (!r->in.buffer && (r->in.offered != 0) ) {
7029                 return WERR_INVALID_PARAM;
7030         }
7031
7032         DEBUG(4,("_spoolss_EnumForms\n"));
7033         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7034         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7035
7036         switch (r->in.level) {
7037         case 1:
7038                 result = winreg_printer_enumforms1(p->mem_ctx,
7039                                                    p->server_info,
7040                                                    p->msg_ctx,
7041                                                    r->out.count,
7042                                                    r->out.info);
7043                 break;
7044         default:
7045                 result = WERR_UNKNOWN_LEVEL;
7046                 break;
7047         }
7048
7049         if (!W_ERROR_IS_OK(result)) {
7050                 return result;
7051         }
7052
7053         if (*r->out.count == 0) {
7054                 return WERR_NO_MORE_ITEMS;
7055         }
7056
7057         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7058                                                      spoolss_EnumForms, 
7059                                                      *r->out.info, r->in.level,
7060                                                      *r->out.count);
7061         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7062         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7063
7064         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7065 }
7066
7067 /****************************************************************
7068  _spoolss_GetForm
7069 ****************************************************************/
7070
7071 WERROR _spoolss_GetForm(struct pipes_struct *p,
7072                         struct spoolss_GetForm *r)
7073 {
7074         WERROR result;
7075
7076         /* that's an [in out] buffer */
7077
7078         if (!r->in.buffer && (r->in.offered != 0)) {
7079                 return WERR_INVALID_PARAM;
7080         }
7081
7082         DEBUG(4,("_spoolss_GetForm\n"));
7083         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7084         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7085
7086         switch (r->in.level) {
7087         case 1:
7088                 result = winreg_printer_getform1(p->mem_ctx,
7089                                                  p->server_info,
7090                                                  p->msg_ctx,
7091                                                  r->in.form_name,
7092                                                  &r->out.info->info1);
7093                 break;
7094         default:
7095                 result = WERR_UNKNOWN_LEVEL;
7096                 break;
7097         }
7098
7099         if (!W_ERROR_IS_OK(result)) {
7100                 TALLOC_FREE(r->out.info);
7101                 return result;
7102         }
7103
7104         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
7105                                                r->out.info, r->in.level);
7106         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7107
7108         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7109 }
7110
7111 /****************************************************************************
7112 ****************************************************************************/
7113
7114 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7115                           struct spoolss_PortInfo1 *r,
7116                           const char *name)
7117 {
7118         r->port_name = talloc_strdup(mem_ctx, name);
7119         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7120
7121         return WERR_OK;
7122 }
7123
7124 /****************************************************************************
7125  TODO: This probably needs distinguish between TCP/IP and Local ports
7126  somehow.
7127 ****************************************************************************/
7128
7129 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7130                           struct spoolss_PortInfo2 *r,
7131                           const char *name)
7132 {
7133         r->port_name = talloc_strdup(mem_ctx, name);
7134         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7135
7136         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7137         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7138
7139         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7140         W_ERROR_HAVE_NO_MEMORY(r->description);
7141
7142         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7143         r->reserved = 0;
7144
7145         return WERR_OK;
7146 }
7147
7148
7149 /****************************************************************************
7150  wrapper around the enumer ports command
7151 ****************************************************************************/
7152
7153 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7154 {
7155         char *cmd = lp_enumports_cmd();
7156         char **qlines = NULL;
7157         char *command = NULL;
7158         int numlines;
7159         int ret;
7160         int fd;
7161
7162         *count = 0;
7163         *lines = NULL;
7164
7165         /* if no hook then just fill in the default port */
7166
7167         if ( !*cmd ) {
7168                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7169                         return WERR_NOMEM;
7170                 }
7171                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7172                         TALLOC_FREE(qlines);
7173                         return WERR_NOMEM;
7174                 }
7175                 qlines[1] = NULL;
7176                 numlines = 1;
7177         }
7178         else {
7179                 /* we have a valid enumport command */
7180
7181                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7182                 if (!command) {
7183                         return WERR_NOMEM;
7184                 }
7185
7186                 DEBUG(10,("Running [%s]\n", command));
7187                 ret = smbrun(command, &fd);
7188                 DEBUG(10,("Returned [%d]\n", ret));
7189                 TALLOC_FREE(command);
7190                 if (ret != 0) {
7191                         if (fd != -1) {
7192                                 close(fd);
7193                         }
7194                         return WERR_ACCESS_DENIED;
7195                 }
7196
7197                 numlines = 0;
7198                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7199                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7200                 close(fd);
7201         }
7202
7203         *count = numlines;
7204         *lines = qlines;
7205
7206         return WERR_OK;
7207 }
7208
7209 /****************************************************************************
7210  enumports level 1.
7211 ****************************************************************************/
7212
7213 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7214                                 union spoolss_PortInfo **info_p,
7215                                 uint32_t *count)
7216 {
7217         union spoolss_PortInfo *info = NULL;
7218         int i=0;
7219         WERROR result = WERR_OK;
7220         char **qlines = NULL;
7221         int numlines = 0;
7222
7223         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7224         if (!W_ERROR_IS_OK(result)) {
7225                 goto out;
7226         }
7227
7228         if (numlines) {
7229                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7230                 if (!info) {
7231                         DEBUG(10,("Returning WERR_NOMEM\n"));
7232                         result = WERR_NOMEM;
7233                         goto out;
7234                 }
7235
7236                 for (i=0; i<numlines; i++) {
7237                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7238                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7239                         if (!W_ERROR_IS_OK(result)) {
7240                                 goto out;
7241                         }
7242                 }
7243         }
7244         TALLOC_FREE(qlines);
7245
7246 out:
7247         if (!W_ERROR_IS_OK(result)) {
7248                 TALLOC_FREE(info);
7249                 TALLOC_FREE(qlines);
7250                 *count = 0;
7251                 *info_p = NULL;
7252                 return result;
7253         }
7254
7255         *info_p = info;
7256         *count = numlines;
7257
7258         return WERR_OK;
7259 }
7260
7261 /****************************************************************************
7262  enumports level 2.
7263 ****************************************************************************/
7264
7265 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7266                                 union spoolss_PortInfo **info_p,
7267                                 uint32_t *count)
7268 {
7269         union spoolss_PortInfo *info = NULL;
7270         int i=0;
7271         WERROR result = WERR_OK;
7272         char **qlines = NULL;
7273         int numlines = 0;
7274
7275         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7276         if (!W_ERROR_IS_OK(result)) {
7277                 goto out;
7278         }
7279
7280         if (numlines) {
7281                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7282                 if (!info) {
7283                         DEBUG(10,("Returning WERR_NOMEM\n"));
7284                         result = WERR_NOMEM;
7285                         goto out;
7286                 }
7287
7288                 for (i=0; i<numlines; i++) {
7289                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7290                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7291                         if (!W_ERROR_IS_OK(result)) {
7292                                 goto out;
7293                         }
7294                 }
7295         }
7296         TALLOC_FREE(qlines);
7297
7298 out:
7299         if (!W_ERROR_IS_OK(result)) {
7300                 TALLOC_FREE(info);
7301                 TALLOC_FREE(qlines);
7302                 *count = 0;
7303                 *info_p = NULL;
7304                 return result;
7305         }
7306
7307         *info_p = info;
7308         *count = numlines;
7309
7310         return WERR_OK;
7311 }
7312
7313 /****************************************************************
7314  _spoolss_EnumPorts
7315 ****************************************************************/
7316
7317 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7318                           struct spoolss_EnumPorts *r)
7319 {
7320         WERROR result;
7321
7322         /* that's an [in out] buffer */
7323
7324         if (!r->in.buffer && (r->in.offered != 0)) {
7325                 return WERR_INVALID_PARAM;
7326         }
7327
7328         DEBUG(4,("_spoolss_EnumPorts\n"));
7329
7330         *r->out.count = 0;
7331         *r->out.needed = 0;
7332         *r->out.info = NULL;
7333
7334         switch (r->in.level) {
7335         case 1:
7336                 result = enumports_level_1(p->mem_ctx, r->out.info,
7337                                            r->out.count);
7338                 break;
7339         case 2:
7340                 result = enumports_level_2(p->mem_ctx, r->out.info,
7341                                            r->out.count);
7342                 break;
7343         default:
7344                 return WERR_UNKNOWN_LEVEL;
7345         }
7346
7347         if (!W_ERROR_IS_OK(result)) {
7348                 return result;
7349         }
7350
7351         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7352                                                      spoolss_EnumPorts, 
7353                                                      *r->out.info, r->in.level,
7354                                                      *r->out.count);
7355         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7356         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7357
7358         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7359 }
7360
7361 /****************************************************************************
7362 ****************************************************************************/
7363
7364 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7365                                            const char *server,
7366                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7367                                            struct spoolss_DeviceMode *devmode,
7368                                            struct security_descriptor *secdesc,
7369                                            struct spoolss_UserLevelCtr *user_ctr,
7370                                            struct policy_handle *handle)
7371 {
7372         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7373         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7374         int     snum;
7375         WERROR err = WERR_OK;
7376
7377         /* samba does not have a concept of local, non-shared printers yet, so
7378          * make sure we always setup sharename - gd */
7379         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7380             (info2->printername != NULL && info2->printername[0] != '\0')) {
7381                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7382                         "no sharename has been set, setting printername %s as sharename\n",
7383                         info2->printername));
7384                 info2->sharename = info2->printername;
7385         }
7386
7387         /* check to see if the printer already exists */
7388         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7389                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7390                         info2->sharename));
7391                 return WERR_PRINTER_ALREADY_EXISTS;
7392         }
7393
7394         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7395                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7396                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7397                                 info2->printername));
7398                         return WERR_PRINTER_ALREADY_EXISTS;
7399                 }
7400         }
7401
7402         /* validate printer info struct */
7403         if (!info2->printername || strlen(info2->printername) == 0) {
7404                 return WERR_INVALID_PRINTER_NAME;
7405         }
7406         if (!info2->portname || strlen(info2->portname) == 0) {
7407                 return WERR_UNKNOWN_PORT;
7408         }
7409         if (!info2->drivername || strlen(info2->drivername) == 0) {
7410                 return WERR_UNKNOWN_PRINTER_DRIVER;
7411         }
7412         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7413                 return WERR_UNKNOWN_PRINTPROCESSOR;
7414         }
7415
7416         /* FIXME!!!  smbd should check to see if the driver is installed before
7417            trying to add a printer like this  --jerry */
7418
7419         if (*lp_addprinter_cmd() ) {
7420                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7421                                        info2, p->client_address,
7422                                        p->msg_ctx) ) {
7423                         return WERR_ACCESS_DENIED;
7424                 }
7425         } else {
7426                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7427                         "smb.conf parameter \"addprinter command\" is defined. This"
7428                         "parameter must exist for this call to succeed\n",
7429                         info2->sharename ));
7430         }
7431
7432         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7433                 return WERR_ACCESS_DENIED;
7434         }
7435
7436         /* you must be a printer admin to add a new printer */
7437         if (!print_access_check(p->server_info, p->msg_ctx, snum,
7438                                 PRINTER_ACCESS_ADMINISTER)) {
7439                 return WERR_ACCESS_DENIED;
7440         }
7441
7442         /*
7443          * Do sanity check on the requested changes for Samba.
7444          */
7445
7446         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7447                 return WERR_INVALID_PARAM;
7448         }
7449
7450         if (devmode == NULL) {
7451                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7452         }
7453
7454         update_dsspooler(p->mem_ctx,
7455                          p->server_info,
7456                          p->msg_ctx,
7457                          0,
7458                          info2,
7459                          NULL);
7460
7461         err = winreg_update_printer(p->mem_ctx,
7462                                     p->server_info,
7463                                     p->msg_ctx,
7464                                     info2->sharename,
7465                                     info2_mask,
7466                                     info2,
7467                                     devmode,
7468                                     secdesc);
7469         if (!W_ERROR_IS_OK(err)) {
7470                 return err;
7471         }
7472
7473         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7474                 /* Handle open failed - remove addition. */
7475                 ZERO_STRUCTP(handle);
7476                 return WERR_ACCESS_DENIED;
7477         }
7478
7479         return WERR_OK;
7480 }
7481
7482 /****************************************************************
7483  _spoolss_AddPrinterEx
7484 ****************************************************************/
7485
7486 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7487                              struct spoolss_AddPrinterEx *r)
7488 {
7489         switch (r->in.info_ctr->level) {
7490         case 1:
7491                 /* we don't handle yet */
7492                 /* but I know what to do ... */
7493                 return WERR_UNKNOWN_LEVEL;
7494         case 2:
7495                 return spoolss_addprinterex_level_2(p, r->in.server,
7496                                                     r->in.info_ctr,
7497                                                     r->in.devmode_ctr->devmode,
7498                                                     r->in.secdesc_ctr->sd,
7499                                                     r->in.userlevel_ctr,
7500                                                     r->out.handle);
7501         default:
7502                 return WERR_UNKNOWN_LEVEL;
7503         }
7504 }
7505
7506 /****************************************************************
7507  _spoolss_AddPrinter
7508 ****************************************************************/
7509
7510 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7511                            struct spoolss_AddPrinter *r)
7512 {
7513         struct spoolss_AddPrinterEx a;
7514         struct spoolss_UserLevelCtr userlevel_ctr;
7515
7516         ZERO_STRUCT(userlevel_ctr);
7517
7518         userlevel_ctr.level = 1;
7519
7520         a.in.server             = r->in.server;
7521         a.in.info_ctr           = r->in.info_ctr;
7522         a.in.devmode_ctr        = r->in.devmode_ctr;
7523         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7524         a.in.userlevel_ctr      = &userlevel_ctr;
7525         a.out.handle            = r->out.handle;
7526
7527         return _spoolss_AddPrinterEx(p, &a);
7528 }
7529
7530 /****************************************************************
7531  _spoolss_AddPrinterDriverEx
7532 ****************************************************************/
7533
7534 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7535                                    struct spoolss_AddPrinterDriverEx *r)
7536 {
7537         WERROR err = WERR_OK;
7538         const char *driver_name = NULL;
7539         uint32_t version;
7540         const char *fn;
7541
7542         switch (p->opnum) {
7543                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7544                         fn = "_spoolss_AddPrinterDriver";
7545                         break;
7546                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7547                         fn = "_spoolss_AddPrinterDriverEx";
7548                         break;
7549                 default:
7550                         return WERR_INVALID_PARAM;
7551         }
7552
7553         /*
7554          * we only support the semantics of AddPrinterDriver()
7555          * i.e. only copy files that are newer than existing ones
7556          */
7557
7558         if (r->in.flags == 0) {
7559                 return WERR_INVALID_PARAM;
7560         }
7561
7562         if (r->in.flags != APD_COPY_NEW_FILES) {
7563                 return WERR_ACCESS_DENIED;
7564         }
7565
7566         /* FIXME */
7567         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7568                 /* Clever hack from Martin Zielinski <mz@seh.de>
7569                  * to allow downgrade from level 8 (Vista).
7570                  */
7571                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7572                         r->in.info_ctr->level));
7573                 return WERR_UNKNOWN_LEVEL;
7574         }
7575
7576         DEBUG(5,("Cleaning driver's information\n"));
7577         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7578         if (!W_ERROR_IS_OK(err))
7579                 goto done;
7580
7581         DEBUG(5,("Moving driver to final destination\n"));
7582         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7583                                                               &err)) ) {
7584                 goto done;
7585         }
7586
7587         err = winreg_add_driver(p->mem_ctx, p->server_info, p->msg_ctx,
7588                                 r->in.info_ctr, &driver_name, &version);
7589         if (!W_ERROR_IS_OK(err)) {
7590                 goto done;
7591         }
7592
7593         /*
7594          * I think this is where he DrvUpgradePrinter() hook would be
7595          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7596          * server.  Right now, we just need to send ourselves a message
7597          * to update each printer bound to this driver.   --jerry
7598          */
7599
7600         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7601                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7602                         fn, driver_name));
7603         }
7604
7605 done:
7606         return err;
7607 }
7608
7609 /****************************************************************
7610  _spoolss_AddPrinterDriver
7611 ****************************************************************/
7612
7613 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7614                                  struct spoolss_AddPrinterDriver *r)
7615 {
7616         struct spoolss_AddPrinterDriverEx a;
7617
7618         switch (r->in.info_ctr->level) {
7619         case 2:
7620         case 3:
7621         case 4:
7622         case 5:
7623                 break;
7624         default:
7625                 return WERR_UNKNOWN_LEVEL;
7626         }
7627
7628         a.in.servername         = r->in.servername;
7629         a.in.info_ctr           = r->in.info_ctr;
7630         a.in.flags              = APD_COPY_NEW_FILES;
7631
7632         return _spoolss_AddPrinterDriverEx(p, &a);
7633 }
7634
7635 /****************************************************************************
7636 ****************************************************************************/
7637
7638 struct _spoolss_paths {
7639         int type;
7640         const char *share;
7641         const char *dir;
7642 };
7643
7644 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7645
7646 static const struct _spoolss_paths spoolss_paths[]= {
7647         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7648         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7649 };
7650
7651 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7652                                           const char *servername,
7653                                           const char *environment,
7654                                           int component,
7655                                           char **path)
7656 {
7657         const char *pservername = NULL;
7658         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7659         const char *short_archi;
7660
7661         *path = NULL;
7662
7663         /* environment may be empty */
7664         if (environment && strlen(environment)) {
7665                 long_archi = environment;
7666         }
7667
7668         /* servername may be empty */
7669         if (servername && strlen(servername)) {
7670                 pservername = canon_servername(servername);
7671
7672                 if (!is_myname_or_ipaddr(pservername)) {
7673                         return WERR_INVALID_PARAM;
7674                 }
7675         }
7676
7677         if (!(short_archi = get_short_archi(long_archi))) {
7678                 return WERR_INVALID_ENVIRONMENT;
7679         }
7680
7681         switch (component) {
7682         case SPOOLSS_PRTPROCS_PATH:
7683         case SPOOLSS_DRIVER_PATH:
7684                 if (pservername) {
7685                         *path = talloc_asprintf(mem_ctx,
7686                                         "\\\\%s\\%s\\%s",
7687                                         pservername,
7688                                         spoolss_paths[component].share,
7689                                         short_archi);
7690                 } else {
7691                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7692                                         SPOOLSS_DEFAULT_SERVER_PATH,
7693                                         spoolss_paths[component].dir,
7694                                         short_archi);
7695                 }
7696                 break;
7697         default:
7698                 return WERR_INVALID_PARAM;
7699         }
7700
7701         if (!*path) {
7702                 return WERR_NOMEM;
7703         }
7704
7705         return WERR_OK;
7706 }
7707
7708 /****************************************************************************
7709 ****************************************************************************/
7710
7711 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7712                                           const char *servername,
7713                                           const char *environment,
7714                                           struct spoolss_DriverDirectoryInfo1 *r)
7715 {
7716         WERROR werr;
7717         char *path = NULL;
7718
7719         werr = compose_spoolss_server_path(mem_ctx,
7720                                            servername,
7721                                            environment,
7722                                            SPOOLSS_DRIVER_PATH,
7723                                            &path);
7724         if (!W_ERROR_IS_OK(werr)) {
7725                 return werr;
7726         }
7727
7728         DEBUG(4,("printer driver directory: [%s]\n", path));
7729
7730         r->directory_name = path;
7731
7732         return WERR_OK;
7733 }
7734
7735 /****************************************************************
7736  _spoolss_GetPrinterDriverDirectory
7737 ****************************************************************/
7738
7739 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
7740                                           struct spoolss_GetPrinterDriverDirectory *r)
7741 {
7742         WERROR werror;
7743
7744         /* that's an [in out] buffer */
7745
7746         if (!r->in.buffer && (r->in.offered != 0)) {
7747                 return WERR_INVALID_PARAM;
7748         }
7749
7750         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7751                 r->in.level));
7752
7753         *r->out.needed = 0;
7754
7755         /* r->in.level is ignored */
7756
7757         werror = getprinterdriverdir_level_1(p->mem_ctx,
7758                                              r->in.server,
7759                                              r->in.environment,
7760                                              &r->out.info->info1);
7761         if (!W_ERROR_IS_OK(werror)) {
7762                 TALLOC_FREE(r->out.info);
7763                 return werror;
7764         }
7765
7766         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7767                                                r->out.info, r->in.level);
7768         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7769
7770         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7771 }
7772
7773 /****************************************************************
7774  _spoolss_EnumPrinterData
7775 ****************************************************************/
7776
7777 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
7778                                 struct spoolss_EnumPrinterData *r)
7779 {
7780         WERROR result;
7781         struct spoolss_EnumPrinterDataEx r2;
7782         uint32_t count;
7783         struct spoolss_PrinterEnumValues *info, *val = NULL;
7784         uint32_t needed;
7785
7786         r2.in.handle    = r->in.handle;
7787         r2.in.key_name  = "PrinterDriverData";
7788         r2.in.offered   = 0;
7789         r2.out.count    = &count;
7790         r2.out.info     = &info;
7791         r2.out.needed   = &needed;
7792
7793         result = _spoolss_EnumPrinterDataEx(p, &r2);
7794         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7795                 r2.in.offered = needed;
7796                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7797         }
7798         if (!W_ERROR_IS_OK(result)) {
7799                 return result;
7800         }
7801
7802         /*
7803          * The NT machine wants to know the biggest size of value and data
7804          *
7805          * cf: MSDN EnumPrinterData remark section
7806          */
7807
7808         if (!r->in.value_offered && !r->in.data_offered) {
7809                 uint32_t biggest_valuesize = 0;
7810                 uint32_t biggest_datasize = 0;
7811                 int i, name_length;
7812
7813                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7814
7815                 for (i=0; i<count; i++) {
7816
7817                         name_length = strlen(info[i].value_name);
7818                         if (strlen(info[i].value_name) > biggest_valuesize) {
7819                                 biggest_valuesize = name_length;
7820                         }
7821
7822                         if (info[i].data_length > biggest_datasize) {
7823                                 biggest_datasize = info[i].data_length;
7824                         }
7825
7826                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7827                                 biggest_datasize));
7828                 }
7829
7830                 /* the value is an UNICODE string but real_value_size is the length
7831                    in bytes including the trailing 0 */
7832
7833                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7834                 *r->out.data_needed  = biggest_datasize;
7835
7836                 DEBUG(6,("final values: [%d], [%d]\n",
7837                         *r->out.value_needed, *r->out.data_needed));
7838
7839                 return WERR_OK;
7840         }
7841
7842         if (r->in.enum_index < count) {
7843                 val = &info[r->in.enum_index];
7844         }
7845
7846         if (val == NULL) {
7847                 /* out_value should default to "" or else NT4 has
7848                    problems unmarshalling the response */
7849
7850                 if (r->in.value_offered) {
7851                         *r->out.value_needed = 1;
7852                         r->out.value_name = talloc_strdup(r, "");
7853                         if (!r->out.value_name) {
7854                                 return WERR_NOMEM;
7855                         }
7856                 } else {
7857                         r->out.value_name = NULL;
7858                         *r->out.value_needed = 0;
7859                 }
7860
7861                 /* the data is counted in bytes */
7862
7863                 *r->out.data_needed = r->in.data_offered;
7864
7865                 result = WERR_NO_MORE_ITEMS;
7866         } else {
7867                 /*
7868                  * the value is:
7869                  * - counted in bytes in the request
7870                  * - counted in UNICODE chars in the max reply
7871                  * - counted in bytes in the real size
7872                  *
7873                  * take a pause *before* coding not *during* coding
7874                  */
7875
7876                 /* name */
7877                 if (r->in.value_offered) {
7878                         r->out.value_name = talloc_strdup(r, val->value_name);
7879                         if (!r->out.value_name) {
7880                                 return WERR_NOMEM;
7881                         }
7882                         *r->out.value_needed = val->value_name_len;
7883                 } else {
7884                         r->out.value_name = NULL;
7885                         *r->out.value_needed = 0;
7886                 }
7887
7888                 /* type */
7889
7890                 *r->out.type = val->type;
7891
7892                 /* data - counted in bytes */
7893
7894                 /*
7895                  * See the section "Dynamically Typed Query Parameters"
7896                  * in MS-RPRN.
7897                  */
7898
7899                 if (r->out.data && val->data && val->data->data &&
7900                                 val->data_length && r->in.data_offered) {
7901                         memcpy(r->out.data, val->data->data,
7902                                 MIN(val->data_length,r->in.data_offered));
7903                 }
7904
7905                 *r->out.data_needed = val->data_length;
7906
7907                 result = WERR_OK;
7908         }
7909
7910         return result;
7911 }
7912
7913 /****************************************************************
7914  _spoolss_SetPrinterData
7915 ****************************************************************/
7916
7917 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
7918                                struct spoolss_SetPrinterData *r)
7919 {
7920         struct spoolss_SetPrinterDataEx r2;
7921
7922         r2.in.handle            = r->in.handle;
7923         r2.in.key_name          = "PrinterDriverData";
7924         r2.in.value_name        = r->in.value_name;
7925         r2.in.type              = r->in.type;
7926         r2.in.data              = r->in.data;
7927         r2.in.offered           = r->in.offered;
7928
7929         return _spoolss_SetPrinterDataEx(p, &r2);
7930 }
7931
7932 /****************************************************************
7933  _spoolss_ResetPrinter
7934 ****************************************************************/
7935
7936 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
7937                              struct spoolss_ResetPrinter *r)
7938 {
7939         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7940         int             snum;
7941
7942         DEBUG(5,("_spoolss_ResetPrinter\n"));
7943
7944         /*
7945          * All we do is to check to see if the handle and queue is valid.
7946          * This call really doesn't mean anything to us because we only
7947          * support RAW printing.   --jerry
7948          */
7949
7950         if (!Printer) {
7951                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7952                         OUR_HANDLE(r->in.handle)));
7953                 return WERR_BADFID;
7954         }
7955
7956         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7957                 return WERR_BADFID;
7958
7959
7960         /* blindly return success */
7961         return WERR_OK;
7962 }
7963
7964 /****************************************************************
7965  _spoolss_DeletePrinterData
7966 ****************************************************************/
7967
7968 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
7969                                   struct spoolss_DeletePrinterData *r)
7970 {
7971         struct spoolss_DeletePrinterDataEx r2;
7972
7973         r2.in.handle            = r->in.handle;
7974         r2.in.key_name          = "PrinterDriverData";
7975         r2.in.value_name        = r->in.value_name;
7976
7977         return _spoolss_DeletePrinterDataEx(p, &r2);
7978 }
7979
7980 /****************************************************************
7981  _spoolss_AddForm
7982 ****************************************************************/
7983
7984 WERROR _spoolss_AddForm(struct pipes_struct *p,
7985                         struct spoolss_AddForm *r)
7986 {
7987         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7988         int snum = -1;
7989         WERROR status = WERR_OK;
7990         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7991
7992         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7993
7994         DEBUG(5,("_spoolss_AddForm\n"));
7995
7996         if (!Printer) {
7997                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7998                         OUR_HANDLE(r->in.handle)));
7999                 return WERR_BADFID;
8000         }
8001
8002         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8003            and not a printer admin, then fail */
8004
8005         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8006              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8007              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8008                                           p->server_info->info3->base.domain.string,
8009                                           NULL,
8010                                           p->server_info->ptok,
8011                                           lp_printer_admin(snum))) {
8012                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8013                 return WERR_ACCESS_DENIED;
8014         }
8015
8016         switch (form->flags) {
8017         case SPOOLSS_FORM_USER:
8018         case SPOOLSS_FORM_BUILTIN:
8019         case SPOOLSS_FORM_PRINTER:
8020                 break;
8021         default:
8022                 return WERR_INVALID_PARAM;
8023         }
8024
8025         status = winreg_printer_addform1(p->mem_ctx, p->server_info,
8026                                          p->msg_ctx, form);
8027         if (!W_ERROR_IS_OK(status)) {
8028                 return status;
8029         }
8030
8031         /*
8032          * ChangeID must always be set if this is a printer
8033          */
8034         if (Printer->printer_type == SPLHND_PRINTER) {
8035                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8036                         return WERR_BADFID;
8037                 }
8038
8039                 status = winreg_printer_update_changeid(p->mem_ctx,
8040                                                         p->server_info,
8041                                                         p->msg_ctx,
8042                                                         lp_const_servicename(snum));
8043                 if (!W_ERROR_IS_OK(status)) {
8044                         return status;
8045                 }
8046         }
8047
8048         return status;
8049 }
8050
8051 /****************************************************************
8052  _spoolss_DeleteForm
8053 ****************************************************************/
8054
8055 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8056                            struct spoolss_DeleteForm *r)
8057 {
8058         const char *form_name = r->in.form_name;
8059         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8060         int snum = -1;
8061         WERROR status = WERR_OK;
8062         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8063
8064         DEBUG(5,("_spoolss_DeleteForm\n"));
8065
8066         if (!Printer) {
8067                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8068                         OUR_HANDLE(r->in.handle)));
8069                 return WERR_BADFID;
8070         }
8071
8072         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8073              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8074              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8075                                           p->server_info->info3->base.domain.string,
8076                                           NULL,
8077                                           p->server_info->ptok,
8078                                           lp_printer_admin(snum))) {
8079                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8080                 return WERR_ACCESS_DENIED;
8081         }
8082
8083         status = winreg_printer_deleteform1(p->mem_ctx,
8084                                             p->server_info,
8085                                             p->msg_ctx,
8086                                             form_name);
8087         if (!W_ERROR_IS_OK(status)) {
8088                 return status;
8089         }
8090
8091         /*
8092          * ChangeID must always be set if this is a printer
8093          */
8094         if (Printer->printer_type == SPLHND_PRINTER) {
8095                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8096                         return WERR_BADFID;
8097                 }
8098
8099                 status = winreg_printer_update_changeid(p->mem_ctx,
8100                                                         p->server_info,
8101                                                         p->msg_ctx,
8102                                                         lp_const_servicename(snum));
8103                 if (!W_ERROR_IS_OK(status)) {
8104                         return status;
8105                 }
8106         }
8107
8108         return status;
8109 }
8110
8111 /****************************************************************
8112  _spoolss_SetForm
8113 ****************************************************************/
8114
8115 WERROR _spoolss_SetForm(struct pipes_struct *p,
8116                         struct spoolss_SetForm *r)
8117 {
8118         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8119         const char *form_name = r->in.form_name;
8120         int snum = -1;
8121         WERROR status = WERR_OK;
8122         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8123
8124         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8125
8126         DEBUG(5,("_spoolss_SetForm\n"));
8127
8128         if (!Printer) {
8129                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8130                         OUR_HANDLE(r->in.handle)));
8131                 return WERR_BADFID;
8132         }
8133
8134         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8135            and not a printer admin, then fail */
8136
8137         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8138              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8139              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8140                                           p->server_info->info3->base.domain.string,
8141                                           NULL,
8142                                           p->server_info->ptok,
8143                                           lp_printer_admin(snum))) {
8144                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8145                 return WERR_ACCESS_DENIED;
8146         }
8147
8148         status = winreg_printer_setform1(p->mem_ctx,
8149                                          p->server_info,
8150                                          p->msg_ctx,
8151                                          form_name,
8152                                          form);
8153         if (!W_ERROR_IS_OK(status)) {
8154                 return status;
8155         }
8156
8157         /*
8158          * ChangeID must always be set if this is a printer
8159          */
8160         if (Printer->printer_type == SPLHND_PRINTER) {
8161                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8162                         return WERR_BADFID;
8163                 }
8164
8165                 status = winreg_printer_update_changeid(p->mem_ctx,
8166                                                         p->server_info,
8167                                                         p->msg_ctx,
8168                                                         lp_const_servicename(snum));
8169                 if (!W_ERROR_IS_OK(status)) {
8170                         return status;
8171                 }
8172         }
8173
8174         return status;
8175 }
8176
8177 /****************************************************************************
8178  fill_print_processor1
8179 ****************************************************************************/
8180
8181 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8182                                     struct spoolss_PrintProcessorInfo1 *r,
8183                                     const char *print_processor_name)
8184 {
8185         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8186         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8187
8188         return WERR_OK;
8189 }
8190
8191 /****************************************************************************
8192  enumprintprocessors level 1.
8193 ****************************************************************************/
8194
8195 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8196                                           union spoolss_PrintProcessorInfo **info_p,
8197                                           uint32_t *count)
8198 {
8199         union spoolss_PrintProcessorInfo *info;
8200         WERROR result;
8201
8202         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8203         W_ERROR_HAVE_NO_MEMORY(info);
8204
8205         *count = 1;
8206
8207         result = fill_print_processor1(info, &info[0].info1, "winprint");
8208         if (!W_ERROR_IS_OK(result)) {
8209                 goto out;
8210         }
8211
8212  out:
8213         if (!W_ERROR_IS_OK(result)) {
8214                 TALLOC_FREE(info);
8215                 *count = 0;
8216                 return result;
8217         }
8218
8219         *info_p = info;
8220
8221         return WERR_OK;
8222 }
8223
8224 /****************************************************************
8225  _spoolss_EnumPrintProcessors
8226 ****************************************************************/
8227
8228 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8229                                     struct spoolss_EnumPrintProcessors *r)
8230 {
8231         WERROR result;
8232
8233         /* that's an [in out] buffer */
8234
8235         if (!r->in.buffer && (r->in.offered != 0)) {
8236                 return WERR_INVALID_PARAM;
8237         }
8238
8239         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8240
8241         /*
8242          * Enumerate the print processors ...
8243          *
8244          * Just reply with "winprint", to keep NT happy
8245          * and I can use my nice printer checker.
8246          */
8247
8248         *r->out.count = 0;
8249         *r->out.needed = 0;
8250         *r->out.info = NULL;
8251
8252         switch (r->in.level) {
8253         case 1:
8254                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8255                                                      r->out.count);
8256                 break;
8257         default:
8258                 return WERR_UNKNOWN_LEVEL;
8259         }
8260
8261         if (!W_ERROR_IS_OK(result)) {
8262                 return result;
8263         }
8264
8265         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8266                                                      spoolss_EnumPrintProcessors,
8267                                                      *r->out.info, r->in.level,
8268                                                      *r->out.count);
8269         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8270         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8271
8272         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8273 }
8274
8275 /****************************************************************************
8276  fill_printprocdatatype1
8277 ****************************************************************************/
8278
8279 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8280                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8281                                       const char *name_array)
8282 {
8283         r->name_array = talloc_strdup(mem_ctx, name_array);
8284         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8285
8286         return WERR_OK;
8287 }
8288
8289 /****************************************************************************
8290  enumprintprocdatatypes level 1.
8291 ****************************************************************************/
8292
8293 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8294                                              union spoolss_PrintProcDataTypesInfo **info_p,
8295                                              uint32_t *count)
8296 {
8297         WERROR result;
8298         union spoolss_PrintProcDataTypesInfo *info;
8299
8300         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8301         W_ERROR_HAVE_NO_MEMORY(info);
8302
8303         *count = 1;
8304
8305         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8306         if (!W_ERROR_IS_OK(result)) {
8307                 goto out;
8308         }
8309
8310  out:
8311         if (!W_ERROR_IS_OK(result)) {
8312                 TALLOC_FREE(info);
8313                 *count = 0;
8314                 return result;
8315         }
8316
8317         *info_p = info;
8318
8319         return WERR_OK;
8320 }
8321
8322 /****************************************************************
8323  _spoolss_EnumPrintProcDataTypes
8324 ****************************************************************/
8325
8326 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8327                                        struct spoolss_EnumPrintProcDataTypes *r)
8328 {
8329         WERROR result;
8330
8331         /* that's an [in out] buffer */
8332
8333         if (!r->in.buffer && (r->in.offered != 0)) {
8334                 return WERR_INVALID_PARAM;
8335         }
8336
8337         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8338
8339         *r->out.count = 0;
8340         *r->out.needed = 0;
8341         *r->out.info = NULL;
8342
8343         switch (r->in.level) {
8344         case 1:
8345                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8346                                                         r->out.count);
8347                 break;
8348         default:
8349                 return WERR_UNKNOWN_LEVEL;
8350         }
8351
8352         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8353                                                      spoolss_EnumPrintProcDataTypes, 
8354                                                      *r->out.info, r->in.level,
8355                                                      *r->out.count);
8356         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8357         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8358
8359         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8360 }
8361
8362 /****************************************************************************
8363  fill_monitor_1
8364 ****************************************************************************/
8365
8366 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8367                              struct spoolss_MonitorInfo1 *r,
8368                              const char *monitor_name)
8369 {
8370         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8371         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8372
8373         return WERR_OK;
8374 }
8375
8376 /****************************************************************************
8377  fill_monitor_2
8378 ****************************************************************************/
8379
8380 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8381                              struct spoolss_MonitorInfo2 *r,
8382                              const char *monitor_name,
8383                              const char *environment,
8384                              const char *dll_name)
8385 {
8386         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8387         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8388         r->environment                  = talloc_strdup(mem_ctx, environment);
8389         W_ERROR_HAVE_NO_MEMORY(r->environment);
8390         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8391         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8392
8393         return WERR_OK;
8394 }
8395
8396 /****************************************************************************
8397  enumprintmonitors level 1.
8398 ****************************************************************************/
8399
8400 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8401                                         union spoolss_MonitorInfo **info_p,
8402                                         uint32_t *count)
8403 {
8404         union spoolss_MonitorInfo *info;
8405         WERROR result = WERR_OK;
8406
8407         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8408         W_ERROR_HAVE_NO_MEMORY(info);
8409
8410         *count = 2;
8411
8412         result = fill_monitor_1(info, &info[0].info1,
8413                                 SPL_LOCAL_PORT);
8414         if (!W_ERROR_IS_OK(result)) {
8415                 goto out;
8416         }
8417
8418         result = fill_monitor_1(info, &info[1].info1,
8419                                 SPL_TCPIP_PORT);
8420         if (!W_ERROR_IS_OK(result)) {
8421                 goto out;
8422         }
8423
8424 out:
8425         if (!W_ERROR_IS_OK(result)) {
8426                 TALLOC_FREE(info);
8427                 *count = 0;
8428                 return result;
8429         }
8430
8431         *info_p = info;
8432
8433         return WERR_OK;
8434 }
8435
8436 /****************************************************************************
8437  enumprintmonitors level 2.
8438 ****************************************************************************/
8439
8440 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8441                                         union spoolss_MonitorInfo **info_p,
8442                                         uint32_t *count)
8443 {
8444         union spoolss_MonitorInfo *info;
8445         WERROR result = WERR_OK;
8446
8447         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8448         W_ERROR_HAVE_NO_MEMORY(info);
8449
8450         *count = 2;
8451
8452         result = fill_monitor_2(info, &info[0].info2,
8453                                 SPL_LOCAL_PORT,
8454                                 "Windows NT X86", /* FIXME */
8455                                 "localmon.dll");
8456         if (!W_ERROR_IS_OK(result)) {
8457                 goto out;
8458         }
8459
8460         result = fill_monitor_2(info, &info[1].info2,
8461                                 SPL_TCPIP_PORT,
8462                                 "Windows NT X86", /* FIXME */
8463                                 "tcpmon.dll");
8464         if (!W_ERROR_IS_OK(result)) {
8465                 goto out;
8466         }
8467
8468 out:
8469         if (!W_ERROR_IS_OK(result)) {
8470                 TALLOC_FREE(info);
8471                 *count = 0;
8472                 return result;
8473         }
8474
8475         *info_p = info;
8476
8477         return WERR_OK;
8478 }
8479
8480 /****************************************************************
8481  _spoolss_EnumMonitors
8482 ****************************************************************/
8483
8484 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8485                              struct spoolss_EnumMonitors *r)
8486 {
8487         WERROR result;
8488
8489         /* that's an [in out] buffer */
8490
8491         if (!r->in.buffer && (r->in.offered != 0)) {
8492                 return WERR_INVALID_PARAM;
8493         }
8494
8495         DEBUG(5,("_spoolss_EnumMonitors\n"));
8496
8497         /*
8498          * Enumerate the print monitors ...
8499          *
8500          * Just reply with "Local Port", to keep NT happy
8501          * and I can use my nice printer checker.
8502          */
8503
8504         *r->out.count = 0;
8505         *r->out.needed = 0;
8506         *r->out.info = NULL;
8507
8508         switch (r->in.level) {
8509         case 1:
8510                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8511                                                    r->out.count);
8512                 break;
8513         case 2:
8514                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8515                                                    r->out.count);
8516                 break;
8517         default:
8518                 return WERR_UNKNOWN_LEVEL;
8519         }
8520
8521         if (!W_ERROR_IS_OK(result)) {
8522                 return result;
8523         }
8524
8525         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8526                                                      spoolss_EnumMonitors, 
8527                                                      *r->out.info, r->in.level,
8528                                                      *r->out.count);
8529         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8530         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8531
8532         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8533 }
8534
8535 /****************************************************************************
8536 ****************************************************************************/
8537
8538 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8539                              const print_queue_struct *queue,
8540                              int count, int snum,
8541                              struct spoolss_PrinterInfo2 *pinfo2,
8542                              uint32_t jobid,
8543                              struct spoolss_JobInfo1 *r)
8544 {
8545         int i = 0;
8546         bool found = false;
8547
8548         for (i=0; i<count; i++) {
8549                 if (queue[i].job == (int)jobid) {
8550                         found = true;
8551                         break;
8552                 }
8553         }
8554
8555         if (found == false) {
8556                 /* NT treats not found as bad param... yet another bad choice */
8557                 return WERR_INVALID_PARAM;
8558         }
8559
8560         return fill_job_info1(mem_ctx,
8561                               r,
8562                               &queue[i],
8563                               i,
8564                               snum,
8565                               pinfo2);
8566 }
8567
8568 /****************************************************************************
8569 ****************************************************************************/
8570
8571 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8572                              const print_queue_struct *queue,
8573                              int count, int snum,
8574                              struct spoolss_PrinterInfo2 *pinfo2,
8575                              uint32_t jobid,
8576                              struct spoolss_JobInfo2 *r)
8577 {
8578         int i = 0;
8579         bool found = false;
8580         struct spoolss_DeviceMode *devmode;
8581         WERROR result;
8582
8583         for (i=0; i<count; i++) {
8584                 if (queue[i].job == (int)jobid) {
8585                         found = true;
8586                         break;
8587                 }
8588         }
8589
8590         if (found == false) {
8591                 /* NT treats not found as bad param... yet another bad
8592                    choice */
8593                 return WERR_INVALID_PARAM;
8594         }
8595
8596         /*
8597          * if the print job does not have a DEVMODE associated with it,
8598          * just use the one for the printer. A NULL devicemode is not
8599          *  a failure condition
8600          */
8601
8602         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8603         if (!devmode) {
8604                 result = spoolss_create_default_devmode(mem_ctx,
8605                                                 pinfo2->printername,
8606                                                 &devmode);
8607                 if (!W_ERROR_IS_OK(result)) {
8608                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8609                         return result;
8610                 }
8611         }
8612
8613         return fill_job_info2(mem_ctx,
8614                               r,
8615                               &queue[i],
8616                               i,
8617                               snum,
8618                               pinfo2,
8619                               devmode);
8620 }
8621
8622 /****************************************************************
8623  _spoolss_GetJob
8624 ****************************************************************/
8625
8626 WERROR _spoolss_GetJob(struct pipes_struct *p,
8627                        struct spoolss_GetJob *r)
8628 {
8629         WERROR result = WERR_OK;
8630         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8631         int snum;
8632         int count;
8633         print_queue_struct      *queue = NULL;
8634         print_status_struct prt_status;
8635
8636         /* that's an [in out] buffer */
8637
8638         if (!r->in.buffer && (r->in.offered != 0)) {
8639                 return WERR_INVALID_PARAM;
8640         }
8641
8642         DEBUG(5,("_spoolss_GetJob\n"));
8643
8644         *r->out.needed = 0;
8645
8646         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8647                 return WERR_BADFID;
8648         }
8649
8650         result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
8651                                     NULL, lp_servicename(snum), &pinfo2);
8652         if (!W_ERROR_IS_OK(result)) {
8653                 return result;
8654         }
8655
8656         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
8657
8658         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8659                      count, prt_status.status, prt_status.message));
8660
8661         switch (r->in.level) {
8662         case 1:
8663                 result = getjob_level_1(p->mem_ctx,
8664                                         queue, count, snum, pinfo2,
8665                                         r->in.job_id, &r->out.info->info1);
8666                 break;
8667         case 2:
8668                 result = getjob_level_2(p->mem_ctx,
8669                                         queue, count, snum, pinfo2,
8670                                         r->in.job_id, &r->out.info->info2);
8671                 break;
8672         default:
8673                 result = WERR_UNKNOWN_LEVEL;
8674                 break;
8675         }
8676
8677         SAFE_FREE(queue);
8678         TALLOC_FREE(pinfo2);
8679
8680         if (!W_ERROR_IS_OK(result)) {
8681                 TALLOC_FREE(r->out.info);
8682                 return result;
8683         }
8684
8685         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8686                                                                                    r->in.level);
8687         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8688
8689         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8690 }
8691
8692 /****************************************************************
8693  _spoolss_GetPrinterDataEx
8694 ****************************************************************/
8695
8696 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8697                                  struct spoolss_GetPrinterDataEx *r)
8698 {
8699
8700         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8701         const char *printer;
8702         int                     snum = 0;
8703         WERROR result = WERR_OK;
8704         DATA_BLOB blob;
8705         enum winreg_Type val_type;
8706         uint8_t *val_data;
8707         uint32_t val_size;
8708
8709
8710         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8711
8712         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8713                 r->in.key_name, r->in.value_name));
8714
8715         /* in case of problem, return some default values */
8716
8717         *r->out.needed  = 0;
8718         *r->out.type    = REG_NONE;
8719
8720         if (!Printer) {
8721                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8722                         OUR_HANDLE(r->in.handle)));
8723                 result = WERR_BADFID;
8724                 goto done;
8725         }
8726
8727         /* Is the handle to a printer or to the server? */
8728
8729         if (Printer->printer_type == SPLHND_SERVER) {
8730
8731                 union spoolss_PrinterData data;
8732
8733                 result = getprinterdata_printer_server(p->mem_ctx,
8734                                                        r->in.value_name,
8735                                                        r->out.type,
8736                                                        &data);
8737                 if (!W_ERROR_IS_OK(result)) {
8738                         return result;
8739                 }
8740
8741                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8742                                                   *r->out.type, &data);
8743                 if (!W_ERROR_IS_OK(result)) {
8744                         return result;
8745                 }
8746
8747                 *r->out.needed = blob.length;
8748
8749                 if (r->in.offered >= *r->out.needed) {
8750                         memcpy(r->out.data, blob.data, blob.length);
8751                 }
8752
8753                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8754         }
8755
8756         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8757                 return WERR_BADFID;
8758         }
8759         printer = lp_const_servicename(snum);
8760
8761         /* check to see if the keyname is valid */
8762         if (!strlen(r->in.key_name)) {
8763                 return WERR_INVALID_PARAM;
8764         }
8765
8766         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8767         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8768             strequal(r->in.value_name, "ChangeId")) {
8769                 *r->out.type = REG_DWORD;
8770                 *r->out.needed = 4;
8771                 if (r->in.offered >= *r->out.needed) {
8772                         uint32_t changeid = 0;
8773
8774                         result = winreg_printer_get_changeid(p->mem_ctx,
8775                                                              p->server_info,
8776                                                              p->msg_ctx,
8777                                                              printer,
8778                                                              &changeid);
8779                         if (!W_ERROR_IS_OK(result)) {
8780                                 return result;
8781                         }
8782
8783                         SIVAL(r->out.data, 0, changeid);
8784                         result = WERR_OK;
8785                 }
8786                 goto done;
8787         }
8788
8789         result = winreg_get_printer_dataex(p->mem_ctx,
8790                                            p->server_info,
8791                                            p->msg_ctx,
8792                                            printer,
8793                                            r->in.key_name,
8794                                            r->in.value_name,
8795                                            &val_type,
8796                                            &val_data,
8797                                            &val_size);
8798         if (!W_ERROR_IS_OK(result)) {
8799                 return result;
8800         }
8801
8802         *r->out.needed = val_size;
8803         *r->out.type = val_type;
8804
8805         if (r->in.offered >= *r->out.needed) {
8806                 memcpy(r->out.data, val_data, val_size);
8807         }
8808
8809  done:
8810         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8811         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8812
8813         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8814 }
8815
8816 /****************************************************************
8817  _spoolss_SetPrinterDataEx
8818 ****************************************************************/
8819
8820 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
8821                                  struct spoolss_SetPrinterDataEx *r)
8822 {
8823         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8824         int                     snum = 0;
8825         WERROR                  result = WERR_OK;
8826         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8827         char                    *oid_string;
8828
8829         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8830
8831         /* From MSDN documentation of SetPrinterDataEx: pass request to
8832            SetPrinterData if key is "PrinterDriverData" */
8833
8834         if (!Printer) {
8835                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8836                         OUR_HANDLE(r->in.handle)));
8837                 return WERR_BADFID;
8838         }
8839
8840         if (Printer->printer_type == SPLHND_SERVER) {
8841                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8842                         "Not implemented for server handles yet\n"));
8843                 return WERR_INVALID_PARAM;
8844         }
8845
8846         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8847                 return WERR_BADFID;
8848         }
8849
8850         /*
8851          * Access check : NT returns "access denied" if you make a
8852          * SetPrinterData call without the necessary privildge.
8853          * we were originally returning OK if nothing changed
8854          * which made Win2k issue **a lot** of SetPrinterData
8855          * when connecting to a printer  --jerry
8856          */
8857
8858         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8859                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8860                         "change denied by handle access permissions\n"));
8861                 return WERR_ACCESS_DENIED;
8862         }
8863
8864         result = winreg_get_printer(Printer, p->server_info, p->msg_ctx,
8865                                     Printer->servername,
8866                                     lp_servicename(snum),
8867                                     &pinfo2);
8868         if (!W_ERROR_IS_OK(result)) {
8869                 return result;
8870         }
8871
8872         /* check for OID in valuename */
8873
8874         oid_string = strchr(r->in.value_name, ',');
8875         if (oid_string) {
8876                 *oid_string = '\0';
8877                 oid_string++;
8878         }
8879
8880         /* save the registry data */
8881
8882         result = winreg_set_printer_dataex(p->mem_ctx,
8883                                            p->server_info,
8884                                            p->msg_ctx,
8885                                            pinfo2->sharename,
8886                                            r->in.key_name,
8887                                            r->in.value_name,
8888                                            r->in.type,
8889                                            r->in.data,
8890                                            r->in.offered);
8891
8892         if (W_ERROR_IS_OK(result)) {
8893                 /* save the OID if one was specified */
8894                 if (oid_string) {
8895                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8896                                 r->in.key_name, SPOOL_OID_KEY);
8897                         if (!str) {
8898                                 result = WERR_NOMEM;
8899                                 goto done;
8900                         }
8901
8902                         /*
8903                          * I'm not checking the status here on purpose.  Don't know
8904                          * if this is right, but I'm returning the status from the
8905                          * previous set_printer_dataex() call.  I have no idea if
8906                          * this is right.    --jerry
8907                          */
8908                         winreg_set_printer_dataex(p->mem_ctx,
8909                                                   p->server_info,
8910                                                   p->msg_ctx,
8911                                                   pinfo2->sharename,
8912                                                   str,
8913                                                   r->in.value_name,
8914                                                   REG_SZ,
8915                                                   (uint8_t *) oid_string,
8916                                                   strlen(oid_string) + 1);
8917                 }
8918
8919                 result = winreg_printer_update_changeid(p->mem_ctx,
8920                                                         p->server_info,
8921                                                         p->msg_ctx,
8922                                                         lp_const_servicename(snum));
8923
8924         }
8925
8926 done:
8927         talloc_free(pinfo2);
8928         return result;
8929 }
8930
8931 /****************************************************************
8932  _spoolss_DeletePrinterDataEx
8933 ****************************************************************/
8934
8935 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
8936                                     struct spoolss_DeletePrinterDataEx *r)
8937 {
8938         const char *printer;
8939         int             snum=0;
8940         WERROR          status = WERR_OK;
8941         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8942
8943         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8944
8945         if (!Printer) {
8946                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8947                         "Invalid handle (%s:%u:%u).\n",
8948                         OUR_HANDLE(r->in.handle)));
8949                 return WERR_BADFID;
8950         }
8951
8952         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8953                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8954                         "printer properties change denied by handle\n"));
8955                 return WERR_ACCESS_DENIED;
8956         }
8957
8958         if (!r->in.value_name || !r->in.key_name) {
8959                 return WERR_NOMEM;
8960         }
8961
8962         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8963                 return WERR_BADFID;
8964         }
8965         printer = lp_const_servicename(snum);
8966
8967         status = winreg_delete_printer_dataex(p->mem_ctx,
8968                                               p->server_info,
8969                                               p->msg_ctx,
8970                                               printer,
8971                                               r->in.key_name,
8972                                               r->in.value_name);
8973         if (W_ERROR_IS_OK(status)) {
8974                 status = winreg_printer_update_changeid(p->mem_ctx,
8975                                                         p->server_info,
8976                                                         p->msg_ctx,
8977                                                         printer);
8978         }
8979
8980         return status;
8981 }
8982
8983 /****************************************************************
8984  _spoolss_EnumPrinterKey
8985 ****************************************************************/
8986
8987 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
8988                                struct spoolss_EnumPrinterKey *r)
8989 {
8990         uint32_t        num_keys;
8991         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8992         int             snum = 0;
8993         WERROR          result = WERR_BADFILE;
8994         const char **array = NULL;
8995         DATA_BLOB blob;
8996
8997         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8998
8999         if (!Printer) {
9000                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9001                         OUR_HANDLE(r->in.handle)));
9002                 return WERR_BADFID;
9003         }
9004
9005         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9006                 return WERR_BADFID;
9007         }
9008
9009         result = winreg_enum_printer_key(p->mem_ctx,
9010                                          p->server_info,
9011                                          p->msg_ctx,
9012                                          lp_const_servicename(snum),
9013                                          r->in.key_name,
9014                                          &num_keys,
9015                                          &array);
9016         if (!W_ERROR_IS_OK(result)) {
9017                 goto done;
9018         }
9019
9020         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9021                 result = WERR_NOMEM;
9022                 goto done;
9023         }
9024
9025         *r->out._ndr_size = r->in.offered / 2;
9026         *r->out.needed = blob.length;
9027
9028         if (r->in.offered < *r->out.needed) {
9029                 result = WERR_MORE_DATA;
9030         } else {
9031                 result = WERR_OK;
9032                 r->out.key_buffer->string_array = array;
9033         }
9034
9035  done:
9036         if (!W_ERROR_IS_OK(result)) {
9037                 TALLOC_FREE(array);
9038                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9039                         *r->out.needed = 0;
9040                 }
9041         }
9042
9043         return result;
9044 }
9045
9046 /****************************************************************
9047  _spoolss_DeletePrinterKey
9048 ****************************************************************/
9049
9050 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9051                                  struct spoolss_DeletePrinterKey *r)
9052 {
9053         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9054         int                     snum=0;
9055         WERROR                  status;
9056         const char *printer;
9057
9058         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9059
9060         if (!Printer) {
9061                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9062                         OUR_HANDLE(r->in.handle)));
9063                 return WERR_BADFID;
9064         }
9065
9066         /* if keyname == NULL, return error */
9067         if ( !r->in.key_name )
9068                 return WERR_INVALID_PARAM;
9069
9070         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9071                 return WERR_BADFID;
9072         }
9073
9074         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9075                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9076                         "printer properties change denied by handle\n"));
9077                 return WERR_ACCESS_DENIED;
9078         }
9079
9080         printer = lp_const_servicename(snum);
9081
9082         /* delete the key and all subkeys */
9083         status = winreg_delete_printer_key(p->mem_ctx,
9084                                            p->server_info,
9085                                            p->msg_ctx,
9086                                            printer,
9087                                            r->in.key_name);
9088         if (W_ERROR_IS_OK(status)) {
9089                 status = winreg_printer_update_changeid(p->mem_ctx,
9090                                                         p->server_info,
9091                                                         p->msg_ctx,
9092                                                         printer);
9093         }
9094
9095         return status;
9096 }
9097
9098 /****************************************************************
9099  _spoolss_EnumPrinterDataEx
9100 ****************************************************************/
9101
9102 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9103                                   struct spoolss_EnumPrinterDataEx *r)
9104 {
9105         uint32_t        count = 0;
9106         struct spoolss_PrinterEnumValues *info = NULL;
9107         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9108         int             snum;
9109         WERROR          result;
9110
9111         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9112
9113         *r->out.count = 0;
9114         *r->out.needed = 0;
9115         *r->out.info = NULL;
9116
9117         if (!Printer) {
9118                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9119                         OUR_HANDLE(r->in.handle)));
9120                 return WERR_BADFID;
9121         }
9122
9123         /*
9124          * first check for a keyname of NULL or "".  Win2k seems to send
9125          * this a lot and we should send back WERR_INVALID_PARAM
9126          * no need to spend time looking up the printer in this case.
9127          * --jerry
9128          */
9129
9130         if (!strlen(r->in.key_name)) {
9131                 result = WERR_INVALID_PARAM;
9132                 goto done;
9133         }
9134
9135         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9136                 return WERR_BADFID;
9137         }
9138
9139         /* now look for a match on the key name */
9140         result = winreg_enum_printer_dataex(p->mem_ctx,
9141                                             p->server_info,
9142                                             p->msg_ctx,
9143                                             lp_const_servicename(snum),
9144                                             r->in.key_name,
9145                                             &count,
9146                                             &info);
9147         if (!W_ERROR_IS_OK(result)) {
9148                 goto done;
9149         }
9150
9151 #if 0 /* FIXME - gd */
9152         /* housekeeping information in the reply */
9153
9154         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9155          * the hand marshalled container size is a multiple
9156          * of 4 bytes for RPC alignment.
9157          */
9158
9159         if (needed % 4) {
9160                 needed += 4-(needed % 4);
9161         }
9162 #endif
9163         *r->out.count   = count;
9164         *r->out.info    = info;
9165
9166  done:
9167         if (!W_ERROR_IS_OK(result)) {
9168                 return result;
9169         }
9170
9171         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9172                                                spoolss_EnumPrinterDataEx, 
9173                                                *r->out.info,
9174                                                *r->out.count);
9175         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9176         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9177
9178         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9179 }
9180
9181 /****************************************************************************
9182 ****************************************************************************/
9183
9184 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9185                                                  const char *servername,
9186                                                  const char *environment,
9187                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9188 {
9189         WERROR werr;
9190         char *path = NULL;
9191
9192         werr = compose_spoolss_server_path(mem_ctx,
9193                                            servername,
9194                                            environment,
9195                                            SPOOLSS_PRTPROCS_PATH,
9196                                            &path);
9197         if (!W_ERROR_IS_OK(werr)) {
9198                 return werr;
9199         }
9200
9201         DEBUG(4,("print processor directory: [%s]\n", path));
9202
9203         r->directory_name = path;
9204
9205         return WERR_OK;
9206 }
9207
9208 /****************************************************************
9209  _spoolss_GetPrintProcessorDirectory
9210 ****************************************************************/
9211
9212 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9213                                            struct spoolss_GetPrintProcessorDirectory *r)
9214 {
9215         WERROR result;
9216
9217         /* that's an [in out] buffer */
9218
9219         if (!r->in.buffer && (r->in.offered != 0)) {
9220                 return WERR_INVALID_PARAM;
9221         }
9222
9223         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9224                 r->in.level));
9225
9226         *r->out.needed = 0;
9227
9228         /* r->in.level is ignored */
9229
9230         /* We always should reply with a local print processor directory so that
9231          * users are not forced to have a [prnproc$] share on the Samba spoolss
9232          * server - Guenther */
9233
9234         result = getprintprocessordirectory_level_1(p->mem_ctx,
9235                                                     NULL, /* r->in.server */
9236                                                     r->in.environment,
9237                                                     &r->out.info->info1);
9238         if (!W_ERROR_IS_OK(result)) {
9239                 TALLOC_FREE(r->out.info);
9240                 return result;
9241         }
9242
9243         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9244                                                                                    r->out.info, r->in.level);
9245         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9246
9247         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9248 }
9249
9250 /*******************************************************************
9251  ********************************************************************/
9252
9253 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9254                                const char *dllname)
9255 {
9256         enum ndr_err_code ndr_err;
9257         struct spoolss_MonitorUi ui;
9258
9259         ui.dll_name = dllname;
9260
9261         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9262                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9263         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9264                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9265         }
9266         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9267 }
9268
9269 /*******************************************************************
9270  Streams the monitor UI DLL name in UNICODE
9271 *******************************************************************/
9272
9273 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9274                                NT_USER_TOKEN *token, DATA_BLOB *in,
9275                                DATA_BLOB *out, uint32_t *needed)
9276 {
9277         const char *dllname = "tcpmonui.dll";
9278
9279         *needed = (strlen(dllname)+1) * 2;
9280
9281         if (out->length < *needed) {
9282                 return WERR_INSUFFICIENT_BUFFER;
9283         }
9284
9285         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9286                 return WERR_NOMEM;
9287         }
9288
9289         return WERR_OK;
9290 }
9291
9292 /*******************************************************************
9293  ********************************************************************/
9294
9295 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9296                              struct spoolss_PortData1 *port1,
9297                              const DATA_BLOB *buf)
9298 {
9299         enum ndr_err_code ndr_err;
9300         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9301                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9302         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9303                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9304         }
9305         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9306 }
9307
9308 /*******************************************************************
9309  ********************************************************************/
9310
9311 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9312                              struct spoolss_PortData2 *port2,
9313                              const DATA_BLOB *buf)
9314 {
9315         enum ndr_err_code ndr_err;
9316         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9317                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9318         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9319                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9320         }
9321         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9322 }
9323
9324 /*******************************************************************
9325  Create a new TCP/IP port
9326 *******************************************************************/
9327
9328 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9329                              NT_USER_TOKEN *token, DATA_BLOB *in,
9330                              DATA_BLOB *out, uint32_t *needed)
9331 {
9332         struct spoolss_PortData1 port1;
9333         struct spoolss_PortData2 port2;
9334         char *device_uri = NULL;
9335         uint32_t version;
9336
9337         const char *portname;
9338         const char *hostaddress;
9339         const char *queue;
9340         uint32_t port_number;
9341         uint32_t protocol;
9342
9343         /* peek for spoolss_PortData version */
9344
9345         if (!in || (in->length < (128 + 4))) {
9346                 return WERR_GENERAL_FAILURE;
9347         }
9348
9349         version = IVAL(in->data, 128);
9350
9351         switch (version) {
9352                 case 1:
9353                         ZERO_STRUCT(port1);
9354
9355                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9356                                 return WERR_NOMEM;
9357                         }
9358
9359                         portname        = port1.portname;
9360                         hostaddress     = port1.hostaddress;
9361                         queue           = port1.queue;
9362                         protocol        = port1.protocol;
9363                         port_number     = port1.port_number;
9364
9365                         break;
9366                 case 2:
9367                         ZERO_STRUCT(port2);
9368
9369                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9370                                 return WERR_NOMEM;
9371                         }
9372
9373                         portname        = port2.portname;
9374                         hostaddress     = port2.hostaddress;
9375                         queue           = port2.queue;
9376                         protocol        = port2.protocol;
9377                         port_number     = port2.port_number;
9378
9379                         break;
9380                 default:
9381                         DEBUG(1,("xcvtcp_addport: "
9382                                 "unknown version of port_data: %d\n", version));
9383                         return WERR_UNKNOWN_PORT;
9384         }
9385
9386         /* create the device URI and call the add_port_hook() */
9387
9388         switch (protocol) {
9389         case PROTOCOL_RAWTCP_TYPE:
9390                 device_uri = talloc_asprintf(mem_ctx,
9391                                 "socket://%s:%d/", hostaddress,
9392                                 port_number);
9393                 break;
9394
9395         case PROTOCOL_LPR_TYPE:
9396                 device_uri = talloc_asprintf(mem_ctx,
9397                         "lpr://%s/%s", hostaddress, queue );
9398                 break;
9399
9400         default:
9401                 return WERR_UNKNOWN_PORT;
9402         }
9403
9404         if (!device_uri) {
9405                 return WERR_NOMEM;
9406         }
9407
9408         return add_port_hook(mem_ctx, token, portname, device_uri);
9409 }
9410
9411 /*******************************************************************
9412 *******************************************************************/
9413
9414 struct xcv_api_table xcvtcp_cmds[] = {
9415         { "MonitorUI",  xcvtcp_monitorui },
9416         { "AddPort",    xcvtcp_addport},
9417         { NULL,         NULL }
9418 };
9419
9420 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9421                                      NT_USER_TOKEN *token, const char *command,
9422                                      DATA_BLOB *inbuf,
9423                                      DATA_BLOB *outbuf,
9424                                      uint32_t *needed )
9425 {
9426         int i;
9427
9428         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9429
9430         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9431                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9432                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9433         }
9434
9435         return WERR_BADFUNC;
9436 }
9437
9438 /*******************************************************************
9439 *******************************************************************/
9440 #if 0   /* don't support management using the "Local Port" monitor */
9441
9442 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9443                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9444                                  DATA_BLOB *out, uint32_t *needed)
9445 {
9446         const char *dllname = "localui.dll";
9447
9448         *needed = (strlen(dllname)+1) * 2;
9449
9450         if (out->length < *needed) {
9451                 return WERR_INSUFFICIENT_BUFFER;
9452         }
9453
9454         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9455                 return WERR_NOMEM;
9456         }
9457
9458         return WERR_OK;
9459 }
9460
9461 /*******************************************************************
9462 *******************************************************************/
9463
9464 struct xcv_api_table xcvlocal_cmds[] = {
9465         { "MonitorUI",  xcvlocal_monitorui },
9466         { NULL,         NULL }
9467 };
9468 #else
9469 struct xcv_api_table xcvlocal_cmds[] = {
9470         { NULL,         NULL }
9471 };
9472 #endif
9473
9474
9475
9476 /*******************************************************************
9477 *******************************************************************/
9478
9479 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9480                                        NT_USER_TOKEN *token, const char *command,
9481                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9482                                        uint32_t *needed)
9483 {
9484         int i;
9485
9486         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9487
9488         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9489                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9490                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9491         }
9492         return WERR_BADFUNC;
9493 }
9494
9495 /****************************************************************
9496  _spoolss_XcvData
9497 ****************************************************************/
9498
9499 WERROR _spoolss_XcvData(struct pipes_struct *p,
9500                         struct spoolss_XcvData *r)
9501 {
9502         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9503         DATA_BLOB out_data = data_blob_null;
9504         WERROR werror;
9505
9506         if (!Printer) {
9507                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9508                         OUR_HANDLE(r->in.handle)));
9509                 return WERR_BADFID;
9510         }
9511
9512         /* Has to be a handle to the TCP/IP port monitor */
9513
9514         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9515                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9516                 return WERR_BADFID;
9517         }
9518
9519         /* requires administrative access to the server */
9520
9521         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9522                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9523                 return WERR_ACCESS_DENIED;
9524         }
9525
9526         /* Allocate the outgoing buffer */
9527
9528         if (r->in.out_data_size) {
9529                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9530                 if (out_data.data == NULL) {
9531                         return WERR_NOMEM;
9532                 }
9533         }
9534
9535         switch ( Printer->printer_type ) {
9536         case SPLHND_PORTMON_TCP:
9537                 werror = process_xcvtcp_command(p->mem_ctx,
9538                                                 p->server_info->ptok,
9539                                                 r->in.function_name,
9540                                                 &r->in.in_data, &out_data,
9541                                                 r->out.needed);
9542                 break;
9543         case SPLHND_PORTMON_LOCAL:
9544                 werror = process_xcvlocal_command(p->mem_ctx,
9545                                                   p->server_info->ptok,
9546                                                   r->in.function_name,
9547                                                   &r->in.in_data, &out_data,
9548                                                   r->out.needed);
9549                 break;
9550         default:
9551                 werror = WERR_INVALID_PRINT_MONITOR;
9552         }
9553
9554         if (!W_ERROR_IS_OK(werror)) {
9555                 return werror;
9556         }
9557
9558         *r->out.status_code = 0;
9559
9560         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9561                 memcpy(r->out.out_data, out_data.data,
9562                         MIN(r->in.out_data_size, out_data.length));
9563         }
9564
9565         return WERR_OK;
9566 }
9567
9568 /****************************************************************
9569  _spoolss_AddPrintProcessor
9570 ****************************************************************/
9571
9572 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9573                                   struct spoolss_AddPrintProcessor *r)
9574 {
9575         /* for now, just indicate success and ignore the add.  We'll
9576            automatically set the winprint processor for printer
9577            entries later.  Used to debug the LexMark Optra S 1855 PCL
9578            driver --jerry */
9579
9580         return WERR_OK;
9581 }
9582
9583 /****************************************************************
9584  _spoolss_AddPort
9585 ****************************************************************/
9586
9587 WERROR _spoolss_AddPort(struct pipes_struct *p,
9588                         struct spoolss_AddPort *r)
9589 {
9590         /* do what w2k3 does */
9591
9592         return WERR_NOT_SUPPORTED;
9593 }
9594
9595 /****************************************************************
9596  _spoolss_GetPrinterDriver
9597 ****************************************************************/
9598
9599 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9600                                  struct spoolss_GetPrinterDriver *r)
9601 {
9602         p->rng_fault_state = true;
9603         return WERR_NOT_SUPPORTED;
9604 }
9605
9606 /****************************************************************
9607  _spoolss_ReadPrinter
9608 ****************************************************************/
9609
9610 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9611                             struct spoolss_ReadPrinter *r)
9612 {
9613         p->rng_fault_state = true;
9614         return WERR_NOT_SUPPORTED;
9615 }
9616
9617 /****************************************************************
9618  _spoolss_WaitForPrinterChange
9619 ****************************************************************/
9620
9621 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9622                                      struct spoolss_WaitForPrinterChange *r)
9623 {
9624         p->rng_fault_state = true;
9625         return WERR_NOT_SUPPORTED;
9626 }
9627
9628 /****************************************************************
9629  _spoolss_ConfigurePort
9630 ****************************************************************/
9631
9632 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9633                               struct spoolss_ConfigurePort *r)
9634 {
9635         p->rng_fault_state = true;
9636         return WERR_NOT_SUPPORTED;
9637 }
9638
9639 /****************************************************************
9640  _spoolss_DeletePort
9641 ****************************************************************/
9642
9643 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9644                            struct spoolss_DeletePort *r)
9645 {
9646         p->rng_fault_state = true;
9647         return WERR_NOT_SUPPORTED;
9648 }
9649
9650 /****************************************************************
9651  _spoolss_CreatePrinterIC
9652 ****************************************************************/
9653
9654 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9655                                 struct spoolss_CreatePrinterIC *r)
9656 {
9657         p->rng_fault_state = true;
9658         return WERR_NOT_SUPPORTED;
9659 }
9660
9661 /****************************************************************
9662  _spoolss_PlayGDIScriptOnPrinterIC
9663 ****************************************************************/
9664
9665 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9666                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9667 {
9668         p->rng_fault_state = true;
9669         return WERR_NOT_SUPPORTED;
9670 }
9671
9672 /****************************************************************
9673  _spoolss_DeletePrinterIC
9674 ****************************************************************/
9675
9676 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9677                                 struct spoolss_DeletePrinterIC *r)
9678 {
9679         p->rng_fault_state = true;
9680         return WERR_NOT_SUPPORTED;
9681 }
9682
9683 /****************************************************************
9684  _spoolss_AddPrinterConnection
9685 ****************************************************************/
9686
9687 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9688                                      struct spoolss_AddPrinterConnection *r)
9689 {
9690         p->rng_fault_state = true;
9691         return WERR_NOT_SUPPORTED;
9692 }
9693
9694 /****************************************************************
9695  _spoolss_DeletePrinterConnection
9696 ****************************************************************/
9697
9698 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9699                                         struct spoolss_DeletePrinterConnection *r)
9700 {
9701         p->rng_fault_state = true;
9702         return WERR_NOT_SUPPORTED;
9703 }
9704
9705 /****************************************************************
9706  _spoolss_PrinterMessageBox
9707 ****************************************************************/
9708
9709 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9710                                   struct spoolss_PrinterMessageBox *r)
9711 {
9712         p->rng_fault_state = true;
9713         return WERR_NOT_SUPPORTED;
9714 }
9715
9716 /****************************************************************
9717  _spoolss_AddMonitor
9718 ****************************************************************/
9719
9720 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9721                            struct spoolss_AddMonitor *r)
9722 {
9723         p->rng_fault_state = true;
9724         return WERR_NOT_SUPPORTED;
9725 }
9726
9727 /****************************************************************
9728  _spoolss_DeleteMonitor
9729 ****************************************************************/
9730
9731 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
9732                               struct spoolss_DeleteMonitor *r)
9733 {
9734         p->rng_fault_state = true;
9735         return WERR_NOT_SUPPORTED;
9736 }
9737
9738 /****************************************************************
9739  _spoolss_DeletePrintProcessor
9740 ****************************************************************/
9741
9742 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
9743                                      struct spoolss_DeletePrintProcessor *r)
9744 {
9745         p->rng_fault_state = true;
9746         return WERR_NOT_SUPPORTED;
9747 }
9748
9749 /****************************************************************
9750  _spoolss_AddPrintProvidor
9751 ****************************************************************/
9752
9753 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
9754                                  struct spoolss_AddPrintProvidor *r)
9755 {
9756         p->rng_fault_state = true;
9757         return WERR_NOT_SUPPORTED;
9758 }
9759
9760 /****************************************************************
9761  _spoolss_DeletePrintProvidor
9762 ****************************************************************/
9763
9764 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
9765                                     struct spoolss_DeletePrintProvidor *r)
9766 {
9767         p->rng_fault_state = true;
9768         return WERR_NOT_SUPPORTED;
9769 }
9770
9771 /****************************************************************
9772  _spoolss_FindFirstPrinterChangeNotification
9773 ****************************************************************/
9774
9775 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
9776                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9777 {
9778         p->rng_fault_state = true;
9779         return WERR_NOT_SUPPORTED;
9780 }
9781
9782 /****************************************************************
9783  _spoolss_FindNextPrinterChangeNotification
9784 ****************************************************************/
9785
9786 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
9787                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9788 {
9789         p->rng_fault_state = true;
9790         return WERR_NOT_SUPPORTED;
9791 }
9792
9793 /****************************************************************
9794  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9795 ****************************************************************/
9796
9797 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
9798                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9799 {
9800         p->rng_fault_state = true;
9801         return WERR_NOT_SUPPORTED;
9802 }
9803
9804 /****************************************************************
9805  _spoolss_ReplyOpenPrinter
9806 ****************************************************************/
9807
9808 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
9809                                  struct spoolss_ReplyOpenPrinter *r)
9810 {
9811         p->rng_fault_state = true;
9812         return WERR_NOT_SUPPORTED;
9813 }
9814
9815 /****************************************************************
9816  _spoolss_RouterReplyPrinter
9817 ****************************************************************/
9818
9819 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
9820                                    struct spoolss_RouterReplyPrinter *r)
9821 {
9822         p->rng_fault_state = true;
9823         return WERR_NOT_SUPPORTED;
9824 }
9825
9826 /****************************************************************
9827  _spoolss_ReplyClosePrinter
9828 ****************************************************************/
9829
9830 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
9831                                   struct spoolss_ReplyClosePrinter *r)
9832 {
9833         p->rng_fault_state = true;
9834         return WERR_NOT_SUPPORTED;
9835 }
9836
9837 /****************************************************************
9838  _spoolss_AddPortEx
9839 ****************************************************************/
9840
9841 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
9842                           struct spoolss_AddPortEx *r)
9843 {
9844         p->rng_fault_state = true;
9845         return WERR_NOT_SUPPORTED;
9846 }
9847
9848 /****************************************************************
9849  _spoolss_RouterFindFirstPrinterChangeNotification
9850 ****************************************************************/
9851
9852 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
9853                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9854 {
9855         p->rng_fault_state = true;
9856         return WERR_NOT_SUPPORTED;
9857 }
9858
9859 /****************************************************************
9860  _spoolss_SpoolerInit
9861 ****************************************************************/
9862
9863 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
9864                             struct spoolss_SpoolerInit *r)
9865 {
9866         p->rng_fault_state = true;
9867         return WERR_NOT_SUPPORTED;
9868 }
9869
9870 /****************************************************************
9871  _spoolss_ResetPrinterEx
9872 ****************************************************************/
9873
9874 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
9875                                struct spoolss_ResetPrinterEx *r)
9876 {
9877         p->rng_fault_state = true;
9878         return WERR_NOT_SUPPORTED;
9879 }
9880
9881 /****************************************************************
9882  _spoolss_RouterReplyPrinterEx
9883 ****************************************************************/
9884
9885 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
9886                                      struct spoolss_RouterReplyPrinterEx *r)
9887 {
9888         p->rng_fault_state = true;
9889         return WERR_NOT_SUPPORTED;
9890 }
9891
9892 /****************************************************************
9893  _spoolss_44
9894 ****************************************************************/
9895
9896 WERROR _spoolss_44(struct pipes_struct *p,
9897                    struct spoolss_44 *r)
9898 {
9899         p->rng_fault_state = true;
9900         return WERR_NOT_SUPPORTED;
9901 }
9902
9903 /****************************************************************
9904  _spoolss_47
9905 ****************************************************************/
9906
9907 WERROR _spoolss_47(struct pipes_struct *p,
9908                    struct spoolss_47 *r)
9909 {
9910         p->rng_fault_state = true;
9911         return WERR_NOT_SUPPORTED;
9912 }
9913
9914 /****************************************************************
9915  _spoolss_4a
9916 ****************************************************************/
9917
9918 WERROR _spoolss_4a(struct pipes_struct *p,
9919                    struct spoolss_4a *r)
9920 {
9921         p->rng_fault_state = true;
9922         return WERR_NOT_SUPPORTED;
9923 }
9924
9925 /****************************************************************
9926  _spoolss_4b
9927 ****************************************************************/
9928
9929 WERROR _spoolss_4b(struct pipes_struct *p,
9930                    struct spoolss_4b *r)
9931 {
9932         p->rng_fault_state = true;
9933         return WERR_NOT_SUPPORTED;
9934 }
9935
9936 /****************************************************************
9937  _spoolss_4c
9938 ****************************************************************/
9939
9940 WERROR _spoolss_4c(struct pipes_struct *p,
9941                    struct spoolss_4c *r)
9942 {
9943         p->rng_fault_state = true;
9944         return WERR_NOT_SUPPORTED;
9945 }
9946
9947 /****************************************************************
9948  _spoolss_53
9949 ****************************************************************/
9950
9951 WERROR _spoolss_53(struct pipes_struct *p,
9952                    struct spoolss_53 *r)
9953 {
9954         p->rng_fault_state = true;
9955         return WERR_NOT_SUPPORTED;
9956 }
9957
9958 /****************************************************************
9959  _spoolss_55
9960 ****************************************************************/
9961
9962 WERROR _spoolss_55(struct pipes_struct *p,
9963                    struct spoolss_55 *r)
9964 {
9965         p->rng_fault_state = true;
9966         return WERR_NOT_SUPPORTED;
9967 }
9968
9969 /****************************************************************
9970  _spoolss_56
9971 ****************************************************************/
9972
9973 WERROR _spoolss_56(struct pipes_struct *p,
9974                    struct spoolss_56 *r)
9975 {
9976         p->rng_fault_state = true;
9977         return WERR_NOT_SUPPORTED;
9978 }
9979
9980 /****************************************************************
9981  _spoolss_57
9982 ****************************************************************/
9983
9984 WERROR _spoolss_57(struct pipes_struct *p,
9985                    struct spoolss_57 *r)
9986 {
9987         p->rng_fault_state = true;
9988         return WERR_NOT_SUPPORTED;
9989 }
9990
9991 /****************************************************************
9992  _spoolss_5a
9993 ****************************************************************/
9994
9995 WERROR _spoolss_5a(struct pipes_struct *p,
9996                    struct spoolss_5a *r)
9997 {
9998         p->rng_fault_state = true;
9999         return WERR_NOT_SUPPORTED;
10000 }
10001
10002 /****************************************************************
10003  _spoolss_5b
10004 ****************************************************************/
10005
10006 WERROR _spoolss_5b(struct pipes_struct *p,
10007                    struct spoolss_5b *r)
10008 {
10009         p->rng_fault_state = true;
10010         return WERR_NOT_SUPPORTED;
10011 }
10012
10013 /****************************************************************
10014  _spoolss_5c
10015 ****************************************************************/
10016
10017 WERROR _spoolss_5c(struct pipes_struct *p,
10018                    struct spoolss_5c *r)
10019 {
10020         p->rng_fault_state = true;
10021         return WERR_NOT_SUPPORTED;
10022 }
10023
10024 /****************************************************************
10025  _spoolss_5d
10026 ****************************************************************/
10027
10028 WERROR _spoolss_5d(struct pipes_struct *p,
10029                    struct spoolss_5d *r)
10030 {
10031         p->rng_fault_state = true;
10032         return WERR_NOT_SUPPORTED;
10033 }
10034
10035 /****************************************************************
10036  _spoolss_5e
10037 ****************************************************************/
10038
10039 WERROR _spoolss_5e(struct pipes_struct *p,
10040                    struct spoolss_5e *r)
10041 {
10042         p->rng_fault_state = true;
10043         return WERR_NOT_SUPPORTED;
10044 }
10045
10046 /****************************************************************
10047  _spoolss_5f
10048 ****************************************************************/
10049
10050 WERROR _spoolss_5f(struct pipes_struct *p,
10051                    struct spoolss_5f *r)
10052 {
10053         p->rng_fault_state = true;
10054         return WERR_NOT_SUPPORTED;
10055 }
10056
10057 /****************************************************************
10058  _spoolss_60
10059 ****************************************************************/
10060
10061 WERROR _spoolss_60(struct pipes_struct *p,
10062                    struct spoolss_60 *r)
10063 {
10064         p->rng_fault_state = true;
10065         return WERR_NOT_SUPPORTED;
10066 }
10067
10068 /****************************************************************
10069  _spoolss_61
10070 ****************************************************************/
10071
10072 WERROR _spoolss_61(struct pipes_struct *p,
10073                    struct spoolss_61 *r)
10074 {
10075         p->rng_fault_state = true;
10076         return WERR_NOT_SUPPORTED;
10077 }
10078
10079 /****************************************************************
10080  _spoolss_62
10081 ****************************************************************/
10082
10083 WERROR _spoolss_62(struct pipes_struct *p,
10084                    struct spoolss_62 *r)
10085 {
10086         p->rng_fault_state = true;
10087         return WERR_NOT_SUPPORTED;
10088 }
10089
10090 /****************************************************************
10091  _spoolss_63
10092 ****************************************************************/
10093
10094 WERROR _spoolss_63(struct pipes_struct *p,
10095                    struct spoolss_63 *r)
10096 {
10097         p->rng_fault_state = true;
10098         return WERR_NOT_SUPPORTED;
10099 }
10100
10101 /****************************************************************
10102  _spoolss_64
10103 ****************************************************************/
10104
10105 WERROR _spoolss_64(struct pipes_struct *p,
10106                    struct spoolss_64 *r)
10107 {
10108         p->rng_fault_state = true;
10109         return WERR_NOT_SUPPORTED;
10110 }
10111
10112 /****************************************************************
10113  _spoolss_65
10114 ****************************************************************/
10115
10116 WERROR _spoolss_65(struct pipes_struct *p,
10117                    struct spoolss_65 *r)
10118 {
10119         p->rng_fault_state = true;
10120         return WERR_NOT_SUPPORTED;
10121 }
10122
10123 /****************************************************************
10124  _spoolss_GetCorePrinterDrivers
10125 ****************************************************************/
10126
10127 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10128                                       struct spoolss_GetCorePrinterDrivers *r)
10129 {
10130         p->rng_fault_state = true;
10131         return WERR_NOT_SUPPORTED;
10132 }
10133
10134 /****************************************************************
10135  _spoolss_67
10136 ****************************************************************/
10137
10138 WERROR _spoolss_67(struct pipes_struct *p,
10139                    struct spoolss_67 *r)
10140 {
10141         p->rng_fault_state = true;
10142         return WERR_NOT_SUPPORTED;
10143 }
10144
10145 /****************************************************************
10146  _spoolss_GetPrinterDriverPackagePath
10147 ****************************************************************/
10148
10149 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10150                                             struct spoolss_GetPrinterDriverPackagePath *r)
10151 {
10152         p->rng_fault_state = true;
10153         return WERR_NOT_SUPPORTED;
10154 }
10155
10156 /****************************************************************
10157  _spoolss_69
10158 ****************************************************************/
10159
10160 WERROR _spoolss_69(struct pipes_struct *p,
10161                    struct spoolss_69 *r)
10162 {
10163         p->rng_fault_state = true;
10164         return WERR_NOT_SUPPORTED;
10165 }
10166
10167 /****************************************************************
10168  _spoolss_6a
10169 ****************************************************************/
10170
10171 WERROR _spoolss_6a(struct pipes_struct *p,
10172                    struct spoolss_6a *r)
10173 {
10174         p->rng_fault_state = true;
10175         return WERR_NOT_SUPPORTED;
10176 }
10177
10178 /****************************************************************
10179  _spoolss_6b
10180 ****************************************************************/
10181
10182 WERROR _spoolss_6b(struct pipes_struct *p,
10183                    struct spoolss_6b *r)
10184 {
10185         p->rng_fault_state = true;
10186         return WERR_NOT_SUPPORTED;
10187 }
10188
10189 /****************************************************************
10190  _spoolss_6c
10191 ****************************************************************/
10192
10193 WERROR _spoolss_6c(struct pipes_struct *p,
10194                    struct spoolss_6c *r)
10195 {
10196         p->rng_fault_state = true;
10197         return WERR_NOT_SUPPORTED;
10198 }
10199
10200 /****************************************************************
10201  _spoolss_6d
10202 ****************************************************************/
10203
10204 WERROR _spoolss_6d(struct pipes_struct *p,
10205                    struct spoolss_6d *r)
10206 {
10207         p->rng_fault_state = true;
10208         return WERR_NOT_SUPPORTED;
10209 }