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