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