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