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