s3: Lift the smbd_messaging_context from winreg_add_driver
[amitay/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry.h"
39 #include "registry/reg_objects.h"
40 #include "include/printing.h"
41 #include "secrets.h"
42 #include "../librpc/gen_ndr/netlogon.h"
43
44 /* macros stolen from s4 spoolss server */
45 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
46         ((info)?ndr_size_##fn(info, level, 0):0)
47
48 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
49         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
50
51 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
52         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
53
54 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
55
56 #undef DBGC_CLASS
57 #define DBGC_CLASS DBGC_RPC_SRV
58
59 static Printer_entry *printers_list;
60
61 typedef struct _counter_printer_0 {
62         struct _counter_printer_0 *next;
63         struct _counter_printer_0 *prev;
64
65         int snum;
66         uint32_t counter;
67 } counter_printer_0;
68
69 static counter_printer_0 *counter_list;
70
71 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
72 static uint32_t smb_connections = 0;
73
74
75 /* Map generic permissions to printer object specific permissions */
76
77 const struct standard_mapping printer_std_mapping = {
78         PRINTER_READ,
79         PRINTER_WRITE,
80         PRINTER_EXECUTE,
81         PRINTER_ALL_ACCESS
82 };
83
84 /* Map generic permissions to print server object specific permissions */
85
86 const struct standard_mapping printserver_std_mapping = {
87         SERVER_READ,
88         SERVER_WRITE,
89         SERVER_EXECUTE,
90         SERVER_ALL_ACCESS
91 };
92
93 /* API table for Xcv Monitor functions */
94
95 struct xcv_api_table {
96         const char *name;
97         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
98 };
99
100 /********************************************************************
101  * Canonicalize servername.
102  ********************************************************************/
103
104 static const char *canon_servername(const char *servername)
105 {
106         const char *pservername = servername;
107         while (*pservername == '\\') {
108                 pservername++;
109         }
110         return pservername;
111 }
112
113 /* translate between internal status numbers and NT status numbers */
114 static int nt_printj_status(int v)
115 {
116         switch (v) {
117         case LPQ_QUEUED:
118                 return 0;
119         case LPQ_PAUSED:
120                 return JOB_STATUS_PAUSED;
121         case LPQ_SPOOLING:
122                 return JOB_STATUS_SPOOLING;
123         case LPQ_PRINTING:
124                 return JOB_STATUS_PRINTING;
125         case LPQ_ERROR:
126                 return JOB_STATUS_ERROR;
127         case LPQ_DELETING:
128                 return JOB_STATUS_DELETING;
129         case LPQ_OFFLINE:
130                 return JOB_STATUS_OFFLINE;
131         case LPQ_PAPEROUT:
132                 return JOB_STATUS_PAPEROUT;
133         case LPQ_PRINTED:
134                 return JOB_STATUS_PRINTED;
135         case LPQ_DELETED:
136                 return JOB_STATUS_DELETED;
137         case LPQ_BLOCKED:
138                 return JOB_STATUS_BLOCKED_DEVQ;
139         case LPQ_USER_INTERVENTION:
140                 return JOB_STATUS_USER_INTERVENTION;
141         }
142         return 0;
143 }
144
145 static int nt_printq_status(int v)
146 {
147         switch (v) {
148         case LPQ_PAUSED:
149                 return PRINTER_STATUS_PAUSED;
150         case LPQ_QUEUED:
151         case LPQ_SPOOLING:
152         case LPQ_PRINTING:
153                 return 0;
154         }
155         return 0;
156 }
157
158 /***************************************************************************
159  Disconnect from the client
160 ****************************************************************************/
161
162 static void srv_spoolss_replycloseprinter(
163         int snum, struct policy_handle *handle,
164         struct messaging_context *msg_ctx)
165 {
166         WERROR result;
167         NTSTATUS status;
168
169         /*
170          * Tell the specific printing tdb we no longer want messages for this printer
171          * by deregistering our PID.
172          */
173
174         if (!print_notify_deregister_pid(snum))
175                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
176
177         /* weird if the test succeeds !!! */
178         if (smb_connections==0) {
179                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
180                 return;
181         }
182
183         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
184                                                   handle,
185                                                   &result);
186         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
187                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
188                         win_errstr(result)));
189
190         /* if it's the last connection, deconnect the IPC$ share */
191         if (smb_connections==1) {
192
193                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
194                 /*
195                  * The above call shuts down the pipe also.
196                  */
197                 notify_cli_pipe = NULL;
198
199                 if (msg_ctx != NULL) {
200                         messaging_deregister(msg_ctx, MSG_PRINTER_NOTIFY2,
201                                              NULL);
202
203                         /*
204                          * Tell the serverid.tdb we're no longer
205                          * interested in printer notify messages.
206                          */
207
208                         serverid_register_msg_flags(
209                                 messaging_server_id(msg_ctx),
210                                 false, FLAG_MSG_PRINT_NOTIFY);
211                 }
212         }
213
214         smb_connections--;
215 }
216
217 /****************************************************************************
218  Functions to free a printer entry datastruct.
219 ****************************************************************************/
220
221 static int printer_entry_destructor(Printer_entry *Printer)
222 {
223         if (Printer->notify.client_connected == true) {
224                 int snum = -1;
225
226                 if ( Printer->printer_type == SPLHND_SERVER) {
227                         snum = -1;
228                         srv_spoolss_replycloseprinter(
229                                 snum, &Printer->notify.client_hnd,
230                                 Printer->notify.msg_ctx);
231                 } else if (Printer->printer_type == SPLHND_PRINTER) {
232                         snum = print_queue_snum(Printer->sharename);
233                         if (snum != -1)
234                                 srv_spoolss_replycloseprinter(
235                                         snum, &Printer->notify.client_hnd,
236                                         Printer->notify.msg_ctx);
237                 }
238         }
239
240         Printer->notify.flags=0;
241         Printer->notify.options=0;
242         Printer->notify.localmachine[0]='\0';
243         Printer->notify.printerlocal=0;
244         TALLOC_FREE(Printer->notify.option);
245         Printer->notify.client_connected = false;
246
247         TALLOC_FREE(Printer->devmode);
248
249         /* Remove from the internal list. */
250         DLIST_REMOVE(printers_list, Printer);
251         return 0;
252 }
253
254 /****************************************************************************
255   find printer index by handle
256 ****************************************************************************/
257
258 static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
259                                                 struct policy_handle *hnd)
260 {
261         Printer_entry *find_printer = NULL;
262
263         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
264                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
265                 return NULL;
266         }
267
268         return find_printer;
269 }
270
271 /****************************************************************************
272  Close printer index by handle.
273 ****************************************************************************/
274
275 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
276 {
277         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
278
279         if (!Printer) {
280                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
281                         OUR_HANDLE(hnd)));
282                 return false;
283         }
284
285         close_policy_hnd(p, hnd);
286
287         return true;
288 }
289
290 /****************************************************************************
291  Delete a printer given a handle.
292 ****************************************************************************/
293
294 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
295                                   const char *sharename,
296                                   struct messaging_context *msg_ctx)
297 {
298         char *cmd = lp_deleteprinter_cmd();
299         char *command = NULL;
300         int ret;
301         SE_PRIV se_printop = SE_PRINT_OPERATOR;
302         bool is_print_op = false;
303
304         /* can't fail if we don't try */
305
306         if ( !*cmd )
307                 return WERR_OK;
308
309         command = talloc_asprintf(ctx,
310                         "%s \"%s\"",
311                         cmd, sharename);
312         if (!command) {
313                 return WERR_NOMEM;
314         }
315         if ( token )
316                 is_print_op = user_has_privileges( token, &se_printop );
317
318         DEBUG(10,("Running [%s]\n", command));
319
320         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
321
322         if ( is_print_op )
323                 become_root();
324
325         if ( (ret = smbrun(command, NULL)) == 0 ) {
326                 /* Tell everyone we updated smb.conf. */
327                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
328         }
329
330         if ( is_print_op )
331                 unbecome_root();
332
333         /********** END SePrintOperatorPrivlege BLOCK **********/
334
335         DEBUGADD(10,("returned [%d]\n", ret));
336
337         TALLOC_FREE(command);
338
339         if (ret != 0)
340                 return WERR_BADFID; /* What to return here? */
341
342         /* go ahead and re-read the services immediately */
343         become_root();
344         reload_services(false);
345         unbecome_root();
346
347         if ( lp_servicenumber( sharename )  > 0 )
348                 return WERR_ACCESS_DENIED;
349
350         return WERR_OK;
351 }
352
353 /****************************************************************************
354  Delete a printer given a handle.
355 ****************************************************************************/
356
357 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
358 {
359         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
360         WERROR result;
361
362         if (!Printer) {
363                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
364                         OUR_HANDLE(hnd)));
365                 return WERR_BADFID;
366         }
367
368         /*
369          * It turns out that Windows allows delete printer on a handle
370          * opened by an admin user, then used on a pipe handle created
371          * by an anonymous user..... but they're working on security.... riiight !
372          * JRA.
373          */
374
375         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
376                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
377                 return WERR_ACCESS_DENIED;
378         }
379
380         /* this does not need a become root since the access check has been
381            done on the handle already */
382
383         result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
384                                            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                                                  p->msg_ctx,
6982                                                  r->in.form_name,
6983                                                  &r->out.info->info1);
6984                 break;
6985         default:
6986                 result = WERR_UNKNOWN_LEVEL;
6987                 break;
6988         }
6989
6990         if (!W_ERROR_IS_OK(result)) {
6991                 TALLOC_FREE(r->out.info);
6992                 return result;
6993         }
6994
6995         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6996                                                r->out.info, r->in.level);
6997         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6998
6999         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7000 }
7001
7002 /****************************************************************************
7003 ****************************************************************************/
7004
7005 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7006                           struct spoolss_PortInfo1 *r,
7007                           const char *name)
7008 {
7009         r->port_name = talloc_strdup(mem_ctx, name);
7010         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7011
7012         return WERR_OK;
7013 }
7014
7015 /****************************************************************************
7016  TODO: This probably needs distinguish between TCP/IP and Local ports
7017  somehow.
7018 ****************************************************************************/
7019
7020 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7021                           struct spoolss_PortInfo2 *r,
7022                           const char *name)
7023 {
7024         r->port_name = talloc_strdup(mem_ctx, name);
7025         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7026
7027         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7028         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7029
7030         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7031         W_ERROR_HAVE_NO_MEMORY(r->description);
7032
7033         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7034         r->reserved = 0;
7035
7036         return WERR_OK;
7037 }
7038
7039
7040 /****************************************************************************
7041  wrapper around the enumer ports command
7042 ****************************************************************************/
7043
7044 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7045 {
7046         char *cmd = lp_enumports_cmd();
7047         char **qlines = NULL;
7048         char *command = NULL;
7049         int numlines;
7050         int ret;
7051         int fd;
7052
7053         *count = 0;
7054         *lines = NULL;
7055
7056         /* if no hook then just fill in the default port */
7057
7058         if ( !*cmd ) {
7059                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7060                         return WERR_NOMEM;
7061                 }
7062                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7063                         TALLOC_FREE(qlines);
7064                         return WERR_NOMEM;
7065                 }
7066                 qlines[1] = NULL;
7067                 numlines = 1;
7068         }
7069         else {
7070                 /* we have a valid enumport command */
7071
7072                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7073                 if (!command) {
7074                         return WERR_NOMEM;
7075                 }
7076
7077                 DEBUG(10,("Running [%s]\n", command));
7078                 ret = smbrun(command, &fd);
7079                 DEBUG(10,("Returned [%d]\n", ret));
7080                 TALLOC_FREE(command);
7081                 if (ret != 0) {
7082                         if (fd != -1) {
7083                                 close(fd);
7084                         }
7085                         return WERR_ACCESS_DENIED;
7086                 }
7087
7088                 numlines = 0;
7089                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7090                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7091                 close(fd);
7092         }
7093
7094         *count = numlines;
7095         *lines = qlines;
7096
7097         return WERR_OK;
7098 }
7099
7100 /****************************************************************************
7101  enumports level 1.
7102 ****************************************************************************/
7103
7104 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7105                                 union spoolss_PortInfo **info_p,
7106                                 uint32_t *count)
7107 {
7108         union spoolss_PortInfo *info = NULL;
7109         int i=0;
7110         WERROR result = WERR_OK;
7111         char **qlines = NULL;
7112         int numlines = 0;
7113
7114         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7115         if (!W_ERROR_IS_OK(result)) {
7116                 goto out;
7117         }
7118
7119         if (numlines) {
7120                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7121                 if (!info) {
7122                         DEBUG(10,("Returning WERR_NOMEM\n"));
7123                         result = WERR_NOMEM;
7124                         goto out;
7125                 }
7126
7127                 for (i=0; i<numlines; i++) {
7128                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7129                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7130                         if (!W_ERROR_IS_OK(result)) {
7131                                 goto out;
7132                         }
7133                 }
7134         }
7135         TALLOC_FREE(qlines);
7136
7137 out:
7138         if (!W_ERROR_IS_OK(result)) {
7139                 TALLOC_FREE(info);
7140                 TALLOC_FREE(qlines);
7141                 *count = 0;
7142                 *info_p = NULL;
7143                 return result;
7144         }
7145
7146         *info_p = info;
7147         *count = numlines;
7148
7149         return WERR_OK;
7150 }
7151
7152 /****************************************************************************
7153  enumports level 2.
7154 ****************************************************************************/
7155
7156 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7157                                 union spoolss_PortInfo **info_p,
7158                                 uint32_t *count)
7159 {
7160         union spoolss_PortInfo *info = NULL;
7161         int i=0;
7162         WERROR result = WERR_OK;
7163         char **qlines = NULL;
7164         int numlines = 0;
7165
7166         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7167         if (!W_ERROR_IS_OK(result)) {
7168                 goto out;
7169         }
7170
7171         if (numlines) {
7172                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7173                 if (!info) {
7174                         DEBUG(10,("Returning WERR_NOMEM\n"));
7175                         result = WERR_NOMEM;
7176                         goto out;
7177                 }
7178
7179                 for (i=0; i<numlines; i++) {
7180                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7181                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7182                         if (!W_ERROR_IS_OK(result)) {
7183                                 goto out;
7184                         }
7185                 }
7186         }
7187         TALLOC_FREE(qlines);
7188
7189 out:
7190         if (!W_ERROR_IS_OK(result)) {
7191                 TALLOC_FREE(info);
7192                 TALLOC_FREE(qlines);
7193                 *count = 0;
7194                 *info_p = NULL;
7195                 return result;
7196         }
7197
7198         *info_p = info;
7199         *count = numlines;
7200
7201         return WERR_OK;
7202 }
7203
7204 /****************************************************************
7205  _spoolss_EnumPorts
7206 ****************************************************************/
7207
7208 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7209                           struct spoolss_EnumPorts *r)
7210 {
7211         WERROR result;
7212
7213         /* that's an [in out] buffer */
7214
7215         if (!r->in.buffer && (r->in.offered != 0)) {
7216                 return WERR_INVALID_PARAM;
7217         }
7218
7219         DEBUG(4,("_spoolss_EnumPorts\n"));
7220
7221         *r->out.count = 0;
7222         *r->out.needed = 0;
7223         *r->out.info = NULL;
7224
7225         switch (r->in.level) {
7226         case 1:
7227                 result = enumports_level_1(p->mem_ctx, r->out.info,
7228                                            r->out.count);
7229                 break;
7230         case 2:
7231                 result = enumports_level_2(p->mem_ctx, r->out.info,
7232                                            r->out.count);
7233                 break;
7234         default:
7235                 return WERR_UNKNOWN_LEVEL;
7236         }
7237
7238         if (!W_ERROR_IS_OK(result)) {
7239                 return result;
7240         }
7241
7242         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7243                                                      spoolss_EnumPorts, 
7244                                                      *r->out.info, r->in.level,
7245                                                      *r->out.count);
7246         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7247         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7248
7249         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7250 }
7251
7252 /****************************************************************************
7253 ****************************************************************************/
7254
7255 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7256                                            const char *server,
7257                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7258                                            struct spoolss_DeviceMode *devmode,
7259                                            struct security_descriptor *secdesc,
7260                                            struct spoolss_UserLevelCtr *user_ctr,
7261                                            struct policy_handle *handle)
7262 {
7263         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7264         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7265         int     snum;
7266         WERROR err = WERR_OK;
7267
7268         /* samba does not have a concept of local, non-shared printers yet, so
7269          * make sure we always setup sharename - gd */
7270         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7271             (info2->printername != NULL && info2->printername[0] != '\0')) {
7272                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7273                         "no sharename has been set, setting printername %s as sharename\n",
7274                         info2->printername));
7275                 info2->sharename = info2->printername;
7276         }
7277
7278         /* check to see if the printer already exists */
7279         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7280                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7281                         info2->sharename));
7282                 return WERR_PRINTER_ALREADY_EXISTS;
7283         }
7284
7285         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7286                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7287                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7288                                 info2->printername));
7289                         return WERR_PRINTER_ALREADY_EXISTS;
7290                 }
7291         }
7292
7293         /* validate printer info struct */
7294         if (!info2->printername || strlen(info2->printername) == 0) {
7295                 return WERR_INVALID_PRINTER_NAME;
7296         }
7297         if (!info2->portname || strlen(info2->portname) == 0) {
7298                 return WERR_UNKNOWN_PORT;
7299         }
7300         if (!info2->drivername || strlen(info2->drivername) == 0) {
7301                 return WERR_UNKNOWN_PRINTER_DRIVER;
7302         }
7303         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7304                 return WERR_UNKNOWN_PRINTPROCESSOR;
7305         }
7306
7307         /* FIXME!!!  smbd should check to see if the driver is installed before
7308            trying to add a printer like this  --jerry */
7309
7310         if (*lp_addprinter_cmd() ) {
7311                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7312                                        info2, p->client_address,
7313                                        p->msg_ctx) ) {
7314                         return WERR_ACCESS_DENIED;
7315                 }
7316         } else {
7317                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7318                         "smb.conf parameter \"addprinter command\" is defined. This"
7319                         "parameter must exist for this call to succeed\n",
7320                         info2->sharename ));
7321         }
7322
7323         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7324                 return WERR_ACCESS_DENIED;
7325         }
7326
7327         /* you must be a printer admin to add a new printer */
7328         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7329                 return WERR_ACCESS_DENIED;
7330         }
7331
7332         /*
7333          * Do sanity check on the requested changes for Samba.
7334          */
7335
7336         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7337                 return WERR_INVALID_PARAM;
7338         }
7339
7340         if (devmode == NULL) {
7341                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7342         }
7343
7344         update_dsspooler(p->mem_ctx,
7345                          p->server_info,
7346                          0,
7347                          info2,
7348                          NULL);
7349
7350         err = winreg_update_printer(p->mem_ctx,
7351                                     p->server_info,
7352                                     p->msg_ctx,
7353                                     info2->sharename,
7354                                     info2_mask,
7355                                     info2,
7356                                     devmode,
7357                                     secdesc);
7358         if (!W_ERROR_IS_OK(err)) {
7359                 return err;
7360         }
7361
7362         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7363                 /* Handle open failed - remove addition. */
7364                 ZERO_STRUCTP(handle);
7365                 return WERR_ACCESS_DENIED;
7366         }
7367
7368         return WERR_OK;
7369 }
7370
7371 /****************************************************************
7372  _spoolss_AddPrinterEx
7373 ****************************************************************/
7374
7375 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7376                              struct spoolss_AddPrinterEx *r)
7377 {
7378         switch (r->in.info_ctr->level) {
7379         case 1:
7380                 /* we don't handle yet */
7381                 /* but I know what to do ... */
7382                 return WERR_UNKNOWN_LEVEL;
7383         case 2:
7384                 return spoolss_addprinterex_level_2(p, r->in.server,
7385                                                     r->in.info_ctr,
7386                                                     r->in.devmode_ctr->devmode,
7387                                                     r->in.secdesc_ctr->sd,
7388                                                     r->in.userlevel_ctr,
7389                                                     r->out.handle);
7390         default:
7391                 return WERR_UNKNOWN_LEVEL;
7392         }
7393 }
7394
7395 /****************************************************************
7396  _spoolss_AddPrinter
7397 ****************************************************************/
7398
7399 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7400                            struct spoolss_AddPrinter *r)
7401 {
7402         struct spoolss_AddPrinterEx a;
7403         struct spoolss_UserLevelCtr userlevel_ctr;
7404
7405         ZERO_STRUCT(userlevel_ctr);
7406
7407         userlevel_ctr.level = 1;
7408
7409         a.in.server             = r->in.server;
7410         a.in.info_ctr           = r->in.info_ctr;
7411         a.in.devmode_ctr        = r->in.devmode_ctr;
7412         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7413         a.in.userlevel_ctr      = &userlevel_ctr;
7414         a.out.handle            = r->out.handle;
7415
7416         return _spoolss_AddPrinterEx(p, &a);
7417 }
7418
7419 /****************************************************************
7420  _spoolss_AddPrinterDriverEx
7421 ****************************************************************/
7422
7423 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7424                                    struct spoolss_AddPrinterDriverEx *r)
7425 {
7426         WERROR err = WERR_OK;
7427         const char *driver_name = NULL;
7428         uint32_t version;
7429         const char *fn;
7430
7431         switch (p->opnum) {
7432                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7433                         fn = "_spoolss_AddPrinterDriver";
7434                         break;
7435                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7436                         fn = "_spoolss_AddPrinterDriverEx";
7437                         break;
7438                 default:
7439                         return WERR_INVALID_PARAM;
7440         }
7441
7442         /*
7443          * we only support the semantics of AddPrinterDriver()
7444          * i.e. only copy files that are newer than existing ones
7445          */
7446
7447         if (r->in.flags == 0) {
7448                 return WERR_INVALID_PARAM;
7449         }
7450
7451         if (r->in.flags != APD_COPY_NEW_FILES) {
7452                 return WERR_ACCESS_DENIED;
7453         }
7454
7455         /* FIXME */
7456         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7457                 /* Clever hack from Martin Zielinski <mz@seh.de>
7458                  * to allow downgrade from level 8 (Vista).
7459                  */
7460                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7461                         r->in.info_ctr->level));
7462                 return WERR_UNKNOWN_LEVEL;
7463         }
7464
7465         DEBUG(5,("Cleaning driver's information\n"));
7466         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7467         if (!W_ERROR_IS_OK(err))
7468                 goto done;
7469
7470         DEBUG(5,("Moving driver to final destination\n"));
7471         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7472                                                               &err)) ) {
7473                 goto done;
7474         }
7475
7476         err = winreg_add_driver(p->mem_ctx, p->server_info, p->msg_ctx,
7477                                 r->in.info_ctr, &driver_name, &version);
7478         if (!W_ERROR_IS_OK(err)) {
7479                 goto done;
7480         }
7481
7482         /*
7483          * I think this is where he DrvUpgradePrinter() hook would be
7484          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7485          * server.  Right now, we just need to send ourselves a message
7486          * to update each printer bound to this driver.   --jerry
7487          */
7488
7489         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7490                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7491                         fn, driver_name));
7492         }
7493
7494 done:
7495         return err;
7496 }
7497
7498 /****************************************************************
7499  _spoolss_AddPrinterDriver
7500 ****************************************************************/
7501
7502 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7503                                  struct spoolss_AddPrinterDriver *r)
7504 {
7505         struct spoolss_AddPrinterDriverEx a;
7506
7507         switch (r->in.info_ctr->level) {
7508         case 2:
7509         case 3:
7510         case 4:
7511         case 5:
7512                 break;
7513         default:
7514                 return WERR_UNKNOWN_LEVEL;
7515         }
7516
7517         a.in.servername         = r->in.servername;
7518         a.in.info_ctr           = r->in.info_ctr;
7519         a.in.flags              = APD_COPY_NEW_FILES;
7520
7521         return _spoolss_AddPrinterDriverEx(p, &a);
7522 }
7523
7524 /****************************************************************************
7525 ****************************************************************************/
7526
7527 struct _spoolss_paths {
7528         int type;
7529         const char *share;
7530         const char *dir;
7531 };
7532
7533 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7534
7535 static const struct _spoolss_paths spoolss_paths[]= {
7536         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7537         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7538 };
7539
7540 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7541                                           const char *servername,
7542                                           const char *environment,
7543                                           int component,
7544                                           char **path)
7545 {
7546         const char *pservername = NULL;
7547         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7548         const char *short_archi;
7549
7550         *path = NULL;
7551
7552         /* environment may be empty */
7553         if (environment && strlen(environment)) {
7554                 long_archi = environment;
7555         }
7556
7557         /* servername may be empty */
7558         if (servername && strlen(servername)) {
7559                 pservername = canon_servername(servername);
7560
7561                 if (!is_myname_or_ipaddr(pservername)) {
7562                         return WERR_INVALID_PARAM;
7563                 }
7564         }
7565
7566         if (!(short_archi = get_short_archi(long_archi))) {
7567                 return WERR_INVALID_ENVIRONMENT;
7568         }
7569
7570         switch (component) {
7571         case SPOOLSS_PRTPROCS_PATH:
7572         case SPOOLSS_DRIVER_PATH:
7573                 if (pservername) {
7574                         *path = talloc_asprintf(mem_ctx,
7575                                         "\\\\%s\\%s\\%s",
7576                                         pservername,
7577                                         spoolss_paths[component].share,
7578                                         short_archi);
7579                 } else {
7580                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7581                                         SPOOLSS_DEFAULT_SERVER_PATH,
7582                                         spoolss_paths[component].dir,
7583                                         short_archi);
7584                 }
7585                 break;
7586         default:
7587                 return WERR_INVALID_PARAM;
7588         }
7589
7590         if (!*path) {
7591                 return WERR_NOMEM;
7592         }
7593
7594         return WERR_OK;
7595 }
7596
7597 /****************************************************************************
7598 ****************************************************************************/
7599
7600 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7601                                           const char *servername,
7602                                           const char *environment,
7603                                           struct spoolss_DriverDirectoryInfo1 *r)
7604 {
7605         WERROR werr;
7606         char *path = NULL;
7607
7608         werr = compose_spoolss_server_path(mem_ctx,
7609                                            servername,
7610                                            environment,
7611                                            SPOOLSS_DRIVER_PATH,
7612                                            &path);
7613         if (!W_ERROR_IS_OK(werr)) {
7614                 return werr;
7615         }
7616
7617         DEBUG(4,("printer driver directory: [%s]\n", path));
7618
7619         r->directory_name = path;
7620
7621         return WERR_OK;
7622 }
7623
7624 /****************************************************************
7625  _spoolss_GetPrinterDriverDirectory
7626 ****************************************************************/
7627
7628 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
7629                                           struct spoolss_GetPrinterDriverDirectory *r)
7630 {
7631         WERROR werror;
7632
7633         /* that's an [in out] buffer */
7634
7635         if (!r->in.buffer && (r->in.offered != 0)) {
7636                 return WERR_INVALID_PARAM;
7637         }
7638
7639         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7640                 r->in.level));
7641
7642         *r->out.needed = 0;
7643
7644         /* r->in.level is ignored */
7645
7646         werror = getprinterdriverdir_level_1(p->mem_ctx,
7647                                              r->in.server,
7648                                              r->in.environment,
7649                                              &r->out.info->info1);
7650         if (!W_ERROR_IS_OK(werror)) {
7651                 TALLOC_FREE(r->out.info);
7652                 return werror;
7653         }
7654
7655         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7656                                                r->out.info, r->in.level);
7657         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7658
7659         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7660 }
7661
7662 /****************************************************************
7663  _spoolss_EnumPrinterData
7664 ****************************************************************/
7665
7666 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
7667                                 struct spoolss_EnumPrinterData *r)
7668 {
7669         WERROR result;
7670         struct spoolss_EnumPrinterDataEx r2;
7671         uint32_t count;
7672         struct spoolss_PrinterEnumValues *info, *val = NULL;
7673         uint32_t needed;
7674
7675         r2.in.handle    = r->in.handle;
7676         r2.in.key_name  = "PrinterDriverData";
7677         r2.in.offered   = 0;
7678         r2.out.count    = &count;
7679         r2.out.info     = &info;
7680         r2.out.needed   = &needed;
7681
7682         result = _spoolss_EnumPrinterDataEx(p, &r2);
7683         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7684                 r2.in.offered = needed;
7685                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7686         }
7687         if (!W_ERROR_IS_OK(result)) {
7688                 return result;
7689         }
7690
7691         /*
7692          * The NT machine wants to know the biggest size of value and data
7693          *
7694          * cf: MSDN EnumPrinterData remark section
7695          */
7696
7697         if (!r->in.value_offered && !r->in.data_offered) {
7698                 uint32_t biggest_valuesize = 0;
7699                 uint32_t biggest_datasize = 0;
7700                 int i, name_length;
7701
7702                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7703
7704                 for (i=0; i<count; i++) {
7705
7706                         name_length = strlen(info[i].value_name);
7707                         if (strlen(info[i].value_name) > biggest_valuesize) {
7708                                 biggest_valuesize = name_length;
7709                         }
7710
7711                         if (info[i].data_length > biggest_datasize) {
7712                                 biggest_datasize = info[i].data_length;
7713                         }
7714
7715                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7716                                 biggest_datasize));
7717                 }
7718
7719                 /* the value is an UNICODE string but real_value_size is the length
7720                    in bytes including the trailing 0 */
7721
7722                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7723                 *r->out.data_needed  = biggest_datasize;
7724
7725                 DEBUG(6,("final values: [%d], [%d]\n",
7726                         *r->out.value_needed, *r->out.data_needed));
7727
7728                 return WERR_OK;
7729         }
7730
7731         if (r->in.enum_index < count) {
7732                 val = &info[r->in.enum_index];
7733         }
7734
7735         if (val == NULL) {
7736                 /* out_value should default to "" or else NT4 has
7737                    problems unmarshalling the response */
7738
7739                 if (r->in.value_offered) {
7740                         *r->out.value_needed = 1;
7741                         r->out.value_name = talloc_strdup(r, "");
7742                         if (!r->out.value_name) {
7743                                 return WERR_NOMEM;
7744                         }
7745                 } else {
7746                         r->out.value_name = NULL;
7747                         *r->out.value_needed = 0;
7748                 }
7749
7750                 /* the data is counted in bytes */
7751
7752                 *r->out.data_needed = r->in.data_offered;
7753
7754                 result = WERR_NO_MORE_ITEMS;
7755         } else {
7756                 /*
7757                  * the value is:
7758                  * - counted in bytes in the request
7759                  * - counted in UNICODE chars in the max reply
7760                  * - counted in bytes in the real size
7761                  *
7762                  * take a pause *before* coding not *during* coding
7763                  */
7764
7765                 /* name */
7766                 if (r->in.value_offered) {
7767                         r->out.value_name = talloc_strdup(r, val->value_name);
7768                         if (!r->out.value_name) {
7769                                 return WERR_NOMEM;
7770                         }
7771                         *r->out.value_needed = val->value_name_len;
7772                 } else {
7773                         r->out.value_name = NULL;
7774                         *r->out.value_needed = 0;
7775                 }
7776
7777                 /* type */
7778
7779                 *r->out.type = val->type;
7780
7781                 /* data - counted in bytes */
7782
7783                 /*
7784                  * See the section "Dynamically Typed Query Parameters"
7785                  * in MS-RPRN.
7786                  */
7787
7788                 if (r->out.data && val->data && val->data->data &&
7789                                 val->data_length && r->in.data_offered) {
7790                         memcpy(r->out.data, val->data->data,
7791                                 MIN(val->data_length,r->in.data_offered));
7792                 }
7793
7794                 *r->out.data_needed = val->data_length;
7795
7796                 result = WERR_OK;
7797         }
7798
7799         return result;
7800 }
7801
7802 /****************************************************************
7803  _spoolss_SetPrinterData
7804 ****************************************************************/
7805
7806 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
7807                                struct spoolss_SetPrinterData *r)
7808 {
7809         struct spoolss_SetPrinterDataEx r2;
7810
7811         r2.in.handle            = r->in.handle;
7812         r2.in.key_name          = "PrinterDriverData";
7813         r2.in.value_name        = r->in.value_name;
7814         r2.in.type              = r->in.type;
7815         r2.in.data              = r->in.data;
7816         r2.in.offered           = r->in.offered;
7817
7818         return _spoolss_SetPrinterDataEx(p, &r2);
7819 }
7820
7821 /****************************************************************
7822  _spoolss_ResetPrinter
7823 ****************************************************************/
7824
7825 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
7826                              struct spoolss_ResetPrinter *r)
7827 {
7828         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7829         int             snum;
7830
7831         DEBUG(5,("_spoolss_ResetPrinter\n"));
7832
7833         /*
7834          * All we do is to check to see if the handle and queue is valid.
7835          * This call really doesn't mean anything to us because we only
7836          * support RAW printing.   --jerry
7837          */
7838
7839         if (!Printer) {
7840                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7841                         OUR_HANDLE(r->in.handle)));
7842                 return WERR_BADFID;
7843         }
7844
7845         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7846                 return WERR_BADFID;
7847
7848
7849         /* blindly return success */
7850         return WERR_OK;
7851 }
7852
7853 /****************************************************************
7854  _spoolss_DeletePrinterData
7855 ****************************************************************/
7856
7857 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
7858                                   struct spoolss_DeletePrinterData *r)
7859 {
7860         struct spoolss_DeletePrinterDataEx r2;
7861
7862         r2.in.handle            = r->in.handle;
7863         r2.in.key_name          = "PrinterDriverData";
7864         r2.in.value_name        = r->in.value_name;
7865
7866         return _spoolss_DeletePrinterDataEx(p, &r2);
7867 }
7868
7869 /****************************************************************
7870  _spoolss_AddForm
7871 ****************************************************************/
7872
7873 WERROR _spoolss_AddForm(struct pipes_struct *p,
7874                         struct spoolss_AddForm *r)
7875 {
7876         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7877         int snum = -1;
7878         WERROR status = WERR_OK;
7879         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7880
7881         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7882
7883         DEBUG(5,("_spoolss_AddForm\n"));
7884
7885         if (!Printer) {
7886                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7887                         OUR_HANDLE(r->in.handle)));
7888                 return WERR_BADFID;
7889         }
7890
7891         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7892            and not a printer admin, then fail */
7893
7894         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7895              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7896              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7897                                           p->server_info->info3->base.domain.string,
7898                                           NULL,
7899                                           p->server_info->ptok,
7900                                           lp_printer_admin(snum))) {
7901                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7902                 return WERR_ACCESS_DENIED;
7903         }
7904
7905         switch (form->flags) {
7906         case SPOOLSS_FORM_USER:
7907         case SPOOLSS_FORM_BUILTIN:
7908         case SPOOLSS_FORM_PRINTER:
7909                 break;
7910         default:
7911                 return WERR_INVALID_PARAM;
7912         }
7913
7914         status = winreg_printer_addform1(p->mem_ctx, p->server_info,
7915                                          p->msg_ctx, form);
7916         if (!W_ERROR_IS_OK(status)) {
7917                 return status;
7918         }
7919
7920         /*
7921          * ChangeID must always be set if this is a printer
7922          */
7923         if (Printer->printer_type == SPLHND_PRINTER) {
7924                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7925                         return WERR_BADFID;
7926                 }
7927
7928                 status = winreg_printer_update_changeid(p->mem_ctx,
7929                                                         p->server_info,
7930                                                         p->msg_ctx,
7931                                                         lp_const_servicename(snum));
7932                 if (!W_ERROR_IS_OK(status)) {
7933                         return status;
7934                 }
7935         }
7936
7937         return status;
7938 }
7939
7940 /****************************************************************
7941  _spoolss_DeleteForm
7942 ****************************************************************/
7943
7944 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
7945                            struct spoolss_DeleteForm *r)
7946 {
7947         const char *form_name = r->in.form_name;
7948         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7949         int snum = -1;
7950         WERROR status = WERR_OK;
7951         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7952
7953         DEBUG(5,("_spoolss_DeleteForm\n"));
7954
7955         if (!Printer) {
7956                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7957                         OUR_HANDLE(r->in.handle)));
7958                 return WERR_BADFID;
7959         }
7960
7961         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7962              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7963              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7964                                           p->server_info->info3->base.domain.string,
7965                                           NULL,
7966                                           p->server_info->ptok,
7967                                           lp_printer_admin(snum))) {
7968                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7969                 return WERR_ACCESS_DENIED;
7970         }
7971
7972         status = winreg_printer_deleteform1(p->mem_ctx,
7973                                             p->server_info,
7974                                             p->msg_ctx,
7975                                             form_name);
7976         if (!W_ERROR_IS_OK(status)) {
7977                 return status;
7978         }
7979
7980         /*
7981          * ChangeID must always be set if this is a printer
7982          */
7983         if (Printer->printer_type == SPLHND_PRINTER) {
7984                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7985                         return WERR_BADFID;
7986                 }
7987
7988                 status = winreg_printer_update_changeid(p->mem_ctx,
7989                                                         p->server_info,
7990                                                         p->msg_ctx,
7991                                                         lp_const_servicename(snum));
7992                 if (!W_ERROR_IS_OK(status)) {
7993                         return status;
7994                 }
7995         }
7996
7997         return status;
7998 }
7999
8000 /****************************************************************
8001  _spoolss_SetForm
8002 ****************************************************************/
8003
8004 WERROR _spoolss_SetForm(struct pipes_struct *p,
8005                         struct spoolss_SetForm *r)
8006 {
8007         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8008         const char *form_name = r->in.form_name;
8009         int snum = -1;
8010         WERROR status = WERR_OK;
8011         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8012
8013         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8014
8015         DEBUG(5,("_spoolss_SetForm\n"));
8016
8017         if (!Printer) {
8018                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8019                         OUR_HANDLE(r->in.handle)));
8020                 return WERR_BADFID;
8021         }
8022
8023         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8024            and not a printer admin, then fail */
8025
8026         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8027              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8028              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8029                                           p->server_info->info3->base.domain.string,
8030                                           NULL,
8031                                           p->server_info->ptok,
8032                                           lp_printer_admin(snum))) {
8033                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8034                 return WERR_ACCESS_DENIED;
8035         }
8036
8037         status = winreg_printer_setform1(p->mem_ctx,
8038                                          p->server_info,
8039                                          p->msg_ctx,
8040                                          form_name,
8041                                          form);
8042         if (!W_ERROR_IS_OK(status)) {
8043                 return status;
8044         }
8045
8046         /*
8047          * ChangeID must always be set if this is a printer
8048          */
8049         if (Printer->printer_type == SPLHND_PRINTER) {
8050                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8051                         return WERR_BADFID;
8052                 }
8053
8054                 status = winreg_printer_update_changeid(p->mem_ctx,
8055                                                         p->server_info,
8056                                                         p->msg_ctx,
8057                                                         lp_const_servicename(snum));
8058                 if (!W_ERROR_IS_OK(status)) {
8059                         return status;
8060                 }
8061         }
8062
8063         return status;
8064 }
8065
8066 /****************************************************************************
8067  fill_print_processor1
8068 ****************************************************************************/
8069
8070 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8071                                     struct spoolss_PrintProcessorInfo1 *r,
8072                                     const char *print_processor_name)
8073 {
8074         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8075         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8076
8077         return WERR_OK;
8078 }
8079
8080 /****************************************************************************
8081  enumprintprocessors level 1.
8082 ****************************************************************************/
8083
8084 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8085                                           union spoolss_PrintProcessorInfo **info_p,
8086                                           uint32_t *count)
8087 {
8088         union spoolss_PrintProcessorInfo *info;
8089         WERROR result;
8090
8091         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8092         W_ERROR_HAVE_NO_MEMORY(info);
8093
8094         *count = 1;
8095
8096         result = fill_print_processor1(info, &info[0].info1, "winprint");
8097         if (!W_ERROR_IS_OK(result)) {
8098                 goto out;
8099         }
8100
8101  out:
8102         if (!W_ERROR_IS_OK(result)) {
8103                 TALLOC_FREE(info);
8104                 *count = 0;
8105                 return result;
8106         }
8107
8108         *info_p = info;
8109
8110         return WERR_OK;
8111 }
8112
8113 /****************************************************************
8114  _spoolss_EnumPrintProcessors
8115 ****************************************************************/
8116
8117 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8118                                     struct spoolss_EnumPrintProcessors *r)
8119 {
8120         WERROR result;
8121
8122         /* that's an [in out] buffer */
8123
8124         if (!r->in.buffer && (r->in.offered != 0)) {
8125                 return WERR_INVALID_PARAM;
8126         }
8127
8128         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8129
8130         /*
8131          * Enumerate the print processors ...
8132          *
8133          * Just reply with "winprint", to keep NT happy
8134          * and I can use my nice printer checker.
8135          */
8136
8137         *r->out.count = 0;
8138         *r->out.needed = 0;
8139         *r->out.info = NULL;
8140
8141         switch (r->in.level) {
8142         case 1:
8143                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8144                                                      r->out.count);
8145                 break;
8146         default:
8147                 return WERR_UNKNOWN_LEVEL;
8148         }
8149
8150         if (!W_ERROR_IS_OK(result)) {
8151                 return result;
8152         }
8153
8154         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8155                                                      spoolss_EnumPrintProcessors,
8156                                                      *r->out.info, r->in.level,
8157                                                      *r->out.count);
8158         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8159         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8160
8161         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8162 }
8163
8164 /****************************************************************************
8165  fill_printprocdatatype1
8166 ****************************************************************************/
8167
8168 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8169                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8170                                       const char *name_array)
8171 {
8172         r->name_array = talloc_strdup(mem_ctx, name_array);
8173         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8174
8175         return WERR_OK;
8176 }
8177
8178 /****************************************************************************
8179  enumprintprocdatatypes level 1.
8180 ****************************************************************************/
8181
8182 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8183                                              union spoolss_PrintProcDataTypesInfo **info_p,
8184                                              uint32_t *count)
8185 {
8186         WERROR result;
8187         union spoolss_PrintProcDataTypesInfo *info;
8188
8189         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8190         W_ERROR_HAVE_NO_MEMORY(info);
8191
8192         *count = 1;
8193
8194         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8195         if (!W_ERROR_IS_OK(result)) {
8196                 goto out;
8197         }
8198
8199  out:
8200         if (!W_ERROR_IS_OK(result)) {
8201                 TALLOC_FREE(info);
8202                 *count = 0;
8203                 return result;
8204         }
8205
8206         *info_p = info;
8207
8208         return WERR_OK;
8209 }
8210
8211 /****************************************************************
8212  _spoolss_EnumPrintProcDataTypes
8213 ****************************************************************/
8214
8215 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8216                                        struct spoolss_EnumPrintProcDataTypes *r)
8217 {
8218         WERROR result;
8219
8220         /* that's an [in out] buffer */
8221
8222         if (!r->in.buffer && (r->in.offered != 0)) {
8223                 return WERR_INVALID_PARAM;
8224         }
8225
8226         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8227
8228         *r->out.count = 0;
8229         *r->out.needed = 0;
8230         *r->out.info = NULL;
8231
8232         switch (r->in.level) {
8233         case 1:
8234                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8235                                                         r->out.count);
8236                 break;
8237         default:
8238                 return WERR_UNKNOWN_LEVEL;
8239         }
8240
8241         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8242                                                      spoolss_EnumPrintProcDataTypes, 
8243                                                      *r->out.info, r->in.level,
8244                                                      *r->out.count);
8245         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8246         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8247
8248         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8249 }
8250
8251 /****************************************************************************
8252  fill_monitor_1
8253 ****************************************************************************/
8254
8255 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8256                              struct spoolss_MonitorInfo1 *r,
8257                              const char *monitor_name)
8258 {
8259         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8260         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8261
8262         return WERR_OK;
8263 }
8264
8265 /****************************************************************************
8266  fill_monitor_2
8267 ****************************************************************************/
8268
8269 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8270                              struct spoolss_MonitorInfo2 *r,
8271                              const char *monitor_name,
8272                              const char *environment,
8273                              const char *dll_name)
8274 {
8275         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8276         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8277         r->environment                  = talloc_strdup(mem_ctx, environment);
8278         W_ERROR_HAVE_NO_MEMORY(r->environment);
8279         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8280         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8281
8282         return WERR_OK;
8283 }
8284
8285 /****************************************************************************
8286  enumprintmonitors level 1.
8287 ****************************************************************************/
8288
8289 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8290                                         union spoolss_MonitorInfo **info_p,
8291                                         uint32_t *count)
8292 {
8293         union spoolss_MonitorInfo *info;
8294         WERROR result = WERR_OK;
8295
8296         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8297         W_ERROR_HAVE_NO_MEMORY(info);
8298
8299         *count = 2;
8300
8301         result = fill_monitor_1(info, &info[0].info1,
8302                                 SPL_LOCAL_PORT);
8303         if (!W_ERROR_IS_OK(result)) {
8304                 goto out;
8305         }
8306
8307         result = fill_monitor_1(info, &info[1].info1,
8308                                 SPL_TCPIP_PORT);
8309         if (!W_ERROR_IS_OK(result)) {
8310                 goto out;
8311         }
8312
8313 out:
8314         if (!W_ERROR_IS_OK(result)) {
8315                 TALLOC_FREE(info);
8316                 *count = 0;
8317                 return result;
8318         }
8319
8320         *info_p = info;
8321
8322         return WERR_OK;
8323 }
8324
8325 /****************************************************************************
8326  enumprintmonitors level 2.
8327 ****************************************************************************/
8328
8329 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8330                                         union spoolss_MonitorInfo **info_p,
8331                                         uint32_t *count)
8332 {
8333         union spoolss_MonitorInfo *info;
8334         WERROR result = WERR_OK;
8335
8336         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8337         W_ERROR_HAVE_NO_MEMORY(info);
8338
8339         *count = 2;
8340
8341         result = fill_monitor_2(info, &info[0].info2,
8342                                 SPL_LOCAL_PORT,
8343                                 "Windows NT X86", /* FIXME */
8344                                 "localmon.dll");
8345         if (!W_ERROR_IS_OK(result)) {
8346                 goto out;
8347         }
8348
8349         result = fill_monitor_2(info, &info[1].info2,
8350                                 SPL_TCPIP_PORT,
8351                                 "Windows NT X86", /* FIXME */
8352                                 "tcpmon.dll");
8353         if (!W_ERROR_IS_OK(result)) {
8354                 goto out;
8355         }
8356
8357 out:
8358         if (!W_ERROR_IS_OK(result)) {
8359                 TALLOC_FREE(info);
8360                 *count = 0;
8361                 return result;
8362         }
8363
8364         *info_p = info;
8365
8366         return WERR_OK;
8367 }
8368
8369 /****************************************************************
8370  _spoolss_EnumMonitors
8371 ****************************************************************/
8372
8373 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8374                              struct spoolss_EnumMonitors *r)
8375 {
8376         WERROR result;
8377
8378         /* that's an [in out] buffer */
8379
8380         if (!r->in.buffer && (r->in.offered != 0)) {
8381                 return WERR_INVALID_PARAM;
8382         }
8383
8384         DEBUG(5,("_spoolss_EnumMonitors\n"));
8385
8386         /*
8387          * Enumerate the print monitors ...
8388          *
8389          * Just reply with "Local Port", to keep NT happy
8390          * and I can use my nice printer checker.
8391          */
8392
8393         *r->out.count = 0;
8394         *r->out.needed = 0;
8395         *r->out.info = NULL;
8396
8397         switch (r->in.level) {
8398         case 1:
8399                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8400                                                    r->out.count);
8401                 break;
8402         case 2:
8403                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8404                                                    r->out.count);
8405                 break;
8406         default:
8407                 return WERR_UNKNOWN_LEVEL;
8408         }
8409
8410         if (!W_ERROR_IS_OK(result)) {
8411                 return result;
8412         }
8413
8414         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8415                                                      spoolss_EnumMonitors, 
8416                                                      *r->out.info, r->in.level,
8417                                                      *r->out.count);
8418         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8419         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8420
8421         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8422 }
8423
8424 /****************************************************************************
8425 ****************************************************************************/
8426
8427 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8428                              const print_queue_struct *queue,
8429                              int count, int snum,
8430                              struct spoolss_PrinterInfo2 *pinfo2,
8431                              uint32_t jobid,
8432                              struct spoolss_JobInfo1 *r)
8433 {
8434         int i = 0;
8435         bool found = false;
8436
8437         for (i=0; i<count; i++) {
8438                 if (queue[i].job == (int)jobid) {
8439                         found = true;
8440                         break;
8441                 }
8442         }
8443
8444         if (found == false) {
8445                 /* NT treats not found as bad param... yet another bad choice */
8446                 return WERR_INVALID_PARAM;
8447         }
8448
8449         return fill_job_info1(mem_ctx,
8450                               r,
8451                               &queue[i],
8452                               i,
8453                               snum,
8454                               pinfo2);
8455 }
8456
8457 /****************************************************************************
8458 ****************************************************************************/
8459
8460 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8461                              const print_queue_struct *queue,
8462                              int count, int snum,
8463                              struct spoolss_PrinterInfo2 *pinfo2,
8464                              uint32_t jobid,
8465                              struct spoolss_JobInfo2 *r)
8466 {
8467         int i = 0;
8468         bool found = false;
8469         struct spoolss_DeviceMode *devmode;
8470         WERROR result;
8471
8472         for (i=0; i<count; i++) {
8473                 if (queue[i].job == (int)jobid) {
8474                         found = true;
8475                         break;
8476                 }
8477         }
8478
8479         if (found == false) {
8480                 /* NT treats not found as bad param... yet another bad
8481                    choice */
8482                 return WERR_INVALID_PARAM;
8483         }
8484
8485         /*
8486          * if the print job does not have a DEVMODE associated with it,
8487          * just use the one for the printer. A NULL devicemode is not
8488          *  a failure condition
8489          */
8490
8491         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8492         if (!devmode) {
8493                 result = spoolss_create_default_devmode(mem_ctx,
8494                                                 pinfo2->printername,
8495                                                 &devmode);
8496                 if (!W_ERROR_IS_OK(result)) {
8497                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8498                         return result;
8499                 }
8500         }
8501
8502         return fill_job_info2(mem_ctx,
8503                               r,
8504                               &queue[i],
8505                               i,
8506                               snum,
8507                               pinfo2,
8508                               devmode);
8509 }
8510
8511 /****************************************************************
8512  _spoolss_GetJob
8513 ****************************************************************/
8514
8515 WERROR _spoolss_GetJob(struct pipes_struct *p,
8516                        struct spoolss_GetJob *r)
8517 {
8518         WERROR result = WERR_OK;
8519         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8520         int snum;
8521         int count;
8522         print_queue_struct      *queue = NULL;
8523         print_status_struct prt_status;
8524
8525         /* that's an [in out] buffer */
8526
8527         if (!r->in.buffer && (r->in.offered != 0)) {
8528                 return WERR_INVALID_PARAM;
8529         }
8530
8531         DEBUG(5,("_spoolss_GetJob\n"));
8532
8533         *r->out.needed = 0;
8534
8535         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8536                 return WERR_BADFID;
8537         }
8538
8539         result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
8540                                     NULL, lp_servicename(snum), &pinfo2);
8541         if (!W_ERROR_IS_OK(result)) {
8542                 return result;
8543         }
8544
8545         count = print_queue_status(snum, &queue, &prt_status);
8546
8547         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8548                      count, prt_status.status, prt_status.message));
8549
8550         switch (r->in.level) {
8551         case 1:
8552                 result = getjob_level_1(p->mem_ctx,
8553                                         queue, count, snum, pinfo2,
8554                                         r->in.job_id, &r->out.info->info1);
8555                 break;
8556         case 2:
8557                 result = getjob_level_2(p->mem_ctx,
8558                                         queue, count, snum, pinfo2,
8559                                         r->in.job_id, &r->out.info->info2);
8560                 break;
8561         default:
8562                 result = WERR_UNKNOWN_LEVEL;
8563                 break;
8564         }
8565
8566         SAFE_FREE(queue);
8567         TALLOC_FREE(pinfo2);
8568
8569         if (!W_ERROR_IS_OK(result)) {
8570                 TALLOC_FREE(r->out.info);
8571                 return result;
8572         }
8573
8574         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8575                                                                                    r->in.level);
8576         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8577
8578         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8579 }
8580
8581 /****************************************************************
8582  _spoolss_GetPrinterDataEx
8583 ****************************************************************/
8584
8585 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8586                                  struct spoolss_GetPrinterDataEx *r)
8587 {
8588
8589         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8590         const char *printer;
8591         int                     snum = 0;
8592         WERROR result = WERR_OK;
8593         DATA_BLOB blob;
8594         enum winreg_Type val_type;
8595         uint8_t *val_data;
8596         uint32_t val_size;
8597
8598
8599         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8600
8601         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8602                 r->in.key_name, r->in.value_name));
8603
8604         /* in case of problem, return some default values */
8605
8606         *r->out.needed  = 0;
8607         *r->out.type    = REG_NONE;
8608
8609         if (!Printer) {
8610                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8611                         OUR_HANDLE(r->in.handle)));
8612                 result = WERR_BADFID;
8613                 goto done;
8614         }
8615
8616         /* Is the handle to a printer or to the server? */
8617
8618         if (Printer->printer_type == SPLHND_SERVER) {
8619
8620                 union spoolss_PrinterData data;
8621
8622                 result = getprinterdata_printer_server(p->mem_ctx,
8623                                                        r->in.value_name,
8624                                                        r->out.type,
8625                                                        &data);
8626                 if (!W_ERROR_IS_OK(result)) {
8627                         return result;
8628                 }
8629
8630                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8631                                                   *r->out.type, &data);
8632                 if (!W_ERROR_IS_OK(result)) {
8633                         return result;
8634                 }
8635
8636                 *r->out.needed = blob.length;
8637
8638                 if (r->in.offered >= *r->out.needed) {
8639                         memcpy(r->out.data, blob.data, blob.length);
8640                 }
8641
8642                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8643         }
8644
8645         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8646                 return WERR_BADFID;
8647         }
8648         printer = lp_const_servicename(snum);
8649
8650         /* check to see if the keyname is valid */
8651         if (!strlen(r->in.key_name)) {
8652                 return WERR_INVALID_PARAM;
8653         }
8654
8655         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8656         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8657             strequal(r->in.value_name, "ChangeId")) {
8658                 *r->out.type = REG_DWORD;
8659                 *r->out.needed = 4;
8660                 if (r->in.offered >= *r->out.needed) {
8661                         uint32_t changeid = 0;
8662
8663                         result = winreg_printer_get_changeid(p->mem_ctx,
8664                                                              p->server_info,
8665                                                              p->msg_ctx,
8666                                                              printer,
8667                                                              &changeid);
8668                         if (!W_ERROR_IS_OK(result)) {
8669                                 return result;
8670                         }
8671
8672                         SIVAL(r->out.data, 0, changeid);
8673                         result = WERR_OK;
8674                 }
8675                 goto done;
8676         }
8677
8678         result = winreg_get_printer_dataex(p->mem_ctx,
8679                                            p->server_info,
8680                                            p->msg_ctx,
8681                                            printer,
8682                                            r->in.key_name,
8683                                            r->in.value_name,
8684                                            &val_type,
8685                                            &val_data,
8686                                            &val_size);
8687         if (!W_ERROR_IS_OK(result)) {
8688                 return result;
8689         }
8690
8691         *r->out.needed = val_size;
8692         *r->out.type = val_type;
8693
8694         if (r->in.offered >= *r->out.needed) {
8695                 memcpy(r->out.data, val_data, val_size);
8696         }
8697
8698  done:
8699         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8700         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8701
8702         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8703 }
8704
8705 /****************************************************************
8706  _spoolss_SetPrinterDataEx
8707 ****************************************************************/
8708
8709 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
8710                                  struct spoolss_SetPrinterDataEx *r)
8711 {
8712         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8713         int                     snum = 0;
8714         WERROR                  result = WERR_OK;
8715         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8716         char                    *oid_string;
8717
8718         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8719
8720         /* From MSDN documentation of SetPrinterDataEx: pass request to
8721            SetPrinterData if key is "PrinterDriverData" */
8722
8723         if (!Printer) {
8724                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8725                         OUR_HANDLE(r->in.handle)));
8726                 return WERR_BADFID;
8727         }
8728
8729         if (Printer->printer_type == SPLHND_SERVER) {
8730                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8731                         "Not implemented for server handles yet\n"));
8732                 return WERR_INVALID_PARAM;
8733         }
8734
8735         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8736                 return WERR_BADFID;
8737         }
8738
8739         /*
8740          * Access check : NT returns "access denied" if you make a
8741          * SetPrinterData call without the necessary privildge.
8742          * we were originally returning OK if nothing changed
8743          * which made Win2k issue **a lot** of SetPrinterData
8744          * when connecting to a printer  --jerry
8745          */
8746
8747         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8748                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8749                         "change denied by handle access permissions\n"));
8750                 return WERR_ACCESS_DENIED;
8751         }
8752
8753         result = winreg_get_printer(Printer, p->server_info, p->msg_ctx,
8754                                     Printer->servername,
8755                                     lp_servicename(snum),
8756                                     &pinfo2);
8757         if (!W_ERROR_IS_OK(result)) {
8758                 return result;
8759         }
8760
8761         /* check for OID in valuename */
8762
8763         oid_string = strchr(r->in.value_name, ',');
8764         if (oid_string) {
8765                 *oid_string = '\0';
8766                 oid_string++;
8767         }
8768
8769         /* save the registry data */
8770
8771         result = winreg_set_printer_dataex(p->mem_ctx,
8772                                            p->server_info,
8773                                            p->msg_ctx,
8774                                            pinfo2->sharename,
8775                                            r->in.key_name,
8776                                            r->in.value_name,
8777                                            r->in.type,
8778                                            r->in.data,
8779                                            r->in.offered);
8780
8781         if (W_ERROR_IS_OK(result)) {
8782                 /* save the OID if one was specified */
8783                 if (oid_string) {
8784                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8785                                 r->in.key_name, SPOOL_OID_KEY);
8786                         if (!str) {
8787                                 result = WERR_NOMEM;
8788                                 goto done;
8789                         }
8790
8791                         /*
8792                          * I'm not checking the status here on purpose.  Don't know
8793                          * if this is right, but I'm returning the status from the
8794                          * previous set_printer_dataex() call.  I have no idea if
8795                          * this is right.    --jerry
8796                          */
8797                         winreg_set_printer_dataex(p->mem_ctx,
8798                                                   p->server_info,
8799                                                   p->msg_ctx,
8800                                                   pinfo2->sharename,
8801                                                   str,
8802                                                   r->in.value_name,
8803                                                   REG_SZ,
8804                                                   (uint8_t *) oid_string,
8805                                                   strlen(oid_string) + 1);
8806                 }
8807
8808                 result = winreg_printer_update_changeid(p->mem_ctx,
8809                                                         p->server_info,
8810                                                         p->msg_ctx,
8811                                                         lp_const_servicename(snum));
8812
8813         }
8814
8815 done:
8816         talloc_free(pinfo2);
8817         return result;
8818 }
8819
8820 /****************************************************************
8821  _spoolss_DeletePrinterDataEx
8822 ****************************************************************/
8823
8824 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
8825                                     struct spoolss_DeletePrinterDataEx *r)
8826 {
8827         const char *printer;
8828         int             snum=0;
8829         WERROR          status = WERR_OK;
8830         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8831
8832         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8833
8834         if (!Printer) {
8835                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8836                         "Invalid handle (%s:%u:%u).\n",
8837                         OUR_HANDLE(r->in.handle)));
8838                 return WERR_BADFID;
8839         }
8840
8841         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8842                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8843                         "printer properties change denied by handle\n"));
8844                 return WERR_ACCESS_DENIED;
8845         }
8846
8847         if (!r->in.value_name || !r->in.key_name) {
8848                 return WERR_NOMEM;
8849         }
8850
8851         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8852                 return WERR_BADFID;
8853         }
8854         printer = lp_const_servicename(snum);
8855
8856         status = winreg_delete_printer_dataex(p->mem_ctx,
8857                                               p->server_info,
8858                                               p->msg_ctx,
8859                                               printer,
8860                                               r->in.key_name,
8861                                               r->in.value_name);
8862         if (W_ERROR_IS_OK(status)) {
8863                 status = winreg_printer_update_changeid(p->mem_ctx,
8864                                                         p->server_info,
8865                                                         p->msg_ctx,
8866                                                         printer);
8867         }
8868
8869         return status;
8870 }
8871
8872 /****************************************************************
8873  _spoolss_EnumPrinterKey
8874 ****************************************************************/
8875
8876 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
8877                                struct spoolss_EnumPrinterKey *r)
8878 {
8879         uint32_t        num_keys;
8880         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8881         int             snum = 0;
8882         WERROR          result = WERR_BADFILE;
8883         const char **array = NULL;
8884         DATA_BLOB blob;
8885
8886         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8887
8888         if (!Printer) {
8889                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8890                         OUR_HANDLE(r->in.handle)));
8891                 return WERR_BADFID;
8892         }
8893
8894         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8895                 return WERR_BADFID;
8896         }
8897
8898         result = winreg_enum_printer_key(p->mem_ctx,
8899                                          p->server_info,
8900                                          p->msg_ctx,
8901                                          lp_const_servicename(snum),
8902                                          r->in.key_name,
8903                                          &num_keys,
8904                                          &array);
8905         if (!W_ERROR_IS_OK(result)) {
8906                 goto done;
8907         }
8908
8909         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8910                 result = WERR_NOMEM;
8911                 goto done;
8912         }
8913
8914         *r->out._ndr_size = r->in.offered / 2;
8915         *r->out.needed = blob.length;
8916
8917         if (r->in.offered < *r->out.needed) {
8918                 result = WERR_MORE_DATA;
8919         } else {
8920                 result = WERR_OK;
8921                 r->out.key_buffer->string_array = array;
8922         }
8923
8924  done:
8925         if (!W_ERROR_IS_OK(result)) {
8926                 TALLOC_FREE(array);
8927                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8928                         *r->out.needed = 0;
8929                 }
8930         }
8931
8932         return result;
8933 }
8934
8935 /****************************************************************
8936  _spoolss_DeletePrinterKey
8937 ****************************************************************/
8938
8939 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
8940                                  struct spoolss_DeletePrinterKey *r)
8941 {
8942         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8943         int                     snum=0;
8944         WERROR                  status;
8945         const char *printer;
8946
8947         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8948
8949         if (!Printer) {
8950                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8951                         OUR_HANDLE(r->in.handle)));
8952                 return WERR_BADFID;
8953         }
8954
8955         /* if keyname == NULL, return error */
8956         if ( !r->in.key_name )
8957                 return WERR_INVALID_PARAM;
8958
8959         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8960                 return WERR_BADFID;
8961         }
8962
8963         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8964                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8965                         "printer properties change denied by handle\n"));
8966                 return WERR_ACCESS_DENIED;
8967         }
8968
8969         printer = lp_const_servicename(snum);
8970
8971         /* delete the key and all subkeys */
8972         status = winreg_delete_printer_key(p->mem_ctx,
8973                                            p->server_info,
8974                                            p->msg_ctx,
8975                                            printer,
8976                                            r->in.key_name);
8977         if (W_ERROR_IS_OK(status)) {
8978                 status = winreg_printer_update_changeid(p->mem_ctx,
8979                                                         p->server_info,
8980                                                         p->msg_ctx,
8981                                                         printer);
8982         }
8983
8984         return status;
8985 }
8986
8987 /****************************************************************
8988  _spoolss_EnumPrinterDataEx
8989 ****************************************************************/
8990
8991 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
8992                                   struct spoolss_EnumPrinterDataEx *r)
8993 {
8994         uint32_t        count = 0;
8995         struct spoolss_PrinterEnumValues *info = NULL;
8996         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8997         int             snum;
8998         WERROR          result;
8999
9000         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9001
9002         *r->out.count = 0;
9003         *r->out.needed = 0;
9004         *r->out.info = NULL;
9005
9006         if (!Printer) {
9007                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9008                         OUR_HANDLE(r->in.handle)));
9009                 return WERR_BADFID;
9010         }
9011
9012         /*
9013          * first check for a keyname of NULL or "".  Win2k seems to send
9014          * this a lot and we should send back WERR_INVALID_PARAM
9015          * no need to spend time looking up the printer in this case.
9016          * --jerry
9017          */
9018
9019         if (!strlen(r->in.key_name)) {
9020                 result = WERR_INVALID_PARAM;
9021                 goto done;
9022         }
9023
9024         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9025                 return WERR_BADFID;
9026         }
9027
9028         /* now look for a match on the key name */
9029         result = winreg_enum_printer_dataex(p->mem_ctx,
9030                                             p->server_info,
9031                                             p->msg_ctx,
9032                                             lp_const_servicename(snum),
9033                                             r->in.key_name,
9034                                             &count,
9035                                             &info);
9036         if (!W_ERROR_IS_OK(result)) {
9037                 goto done;
9038         }
9039
9040 #if 0 /* FIXME - gd */
9041         /* housekeeping information in the reply */
9042
9043         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9044          * the hand marshalled container size is a multiple
9045          * of 4 bytes for RPC alignment.
9046          */
9047
9048         if (needed % 4) {
9049                 needed += 4-(needed % 4);
9050         }
9051 #endif
9052         *r->out.count   = count;
9053         *r->out.info    = info;
9054
9055  done:
9056         if (!W_ERROR_IS_OK(result)) {
9057                 return result;
9058         }
9059
9060         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9061                                                spoolss_EnumPrinterDataEx, 
9062                                                *r->out.info,
9063                                                *r->out.count);
9064         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9065         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9066
9067         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9068 }
9069
9070 /****************************************************************************
9071 ****************************************************************************/
9072
9073 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9074                                                  const char *servername,
9075                                                  const char *environment,
9076                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9077 {
9078         WERROR werr;
9079         char *path = NULL;
9080
9081         werr = compose_spoolss_server_path(mem_ctx,
9082                                            servername,
9083                                            environment,
9084                                            SPOOLSS_PRTPROCS_PATH,
9085                                            &path);
9086         if (!W_ERROR_IS_OK(werr)) {
9087                 return werr;
9088         }
9089
9090         DEBUG(4,("print processor directory: [%s]\n", path));
9091
9092         r->directory_name = path;
9093
9094         return WERR_OK;
9095 }
9096
9097 /****************************************************************
9098  _spoolss_GetPrintProcessorDirectory
9099 ****************************************************************/
9100
9101 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9102                                            struct spoolss_GetPrintProcessorDirectory *r)
9103 {
9104         WERROR result;
9105
9106         /* that's an [in out] buffer */
9107
9108         if (!r->in.buffer && (r->in.offered != 0)) {
9109                 return WERR_INVALID_PARAM;
9110         }
9111
9112         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9113                 r->in.level));
9114
9115         *r->out.needed = 0;
9116
9117         /* r->in.level is ignored */
9118
9119         /* We always should reply with a local print processor directory so that
9120          * users are not forced to have a [prnproc$] share on the Samba spoolss
9121          * server - Guenther */
9122
9123         result = getprintprocessordirectory_level_1(p->mem_ctx,
9124                                                     NULL, /* r->in.server */
9125                                                     r->in.environment,
9126                                                     &r->out.info->info1);
9127         if (!W_ERROR_IS_OK(result)) {
9128                 TALLOC_FREE(r->out.info);
9129                 return result;
9130         }
9131
9132         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9133                                                                                    r->out.info, r->in.level);
9134         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9135
9136         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9137 }
9138
9139 /*******************************************************************
9140  ********************************************************************/
9141
9142 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9143                                const char *dllname)
9144 {
9145         enum ndr_err_code ndr_err;
9146         struct spoolss_MonitorUi ui;
9147
9148         ui.dll_name = dllname;
9149
9150         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9151                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9152         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9153                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9154         }
9155         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9156 }
9157
9158 /*******************************************************************
9159  Streams the monitor UI DLL name in UNICODE
9160 *******************************************************************/
9161
9162 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9163                                NT_USER_TOKEN *token, DATA_BLOB *in,
9164                                DATA_BLOB *out, uint32_t *needed)
9165 {
9166         const char *dllname = "tcpmonui.dll";
9167
9168         *needed = (strlen(dllname)+1) * 2;
9169
9170         if (out->length < *needed) {
9171                 return WERR_INSUFFICIENT_BUFFER;
9172         }
9173
9174         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9175                 return WERR_NOMEM;
9176         }
9177
9178         return WERR_OK;
9179 }
9180
9181 /*******************************************************************
9182  ********************************************************************/
9183
9184 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9185                              struct spoolss_PortData1 *port1,
9186                              const DATA_BLOB *buf)
9187 {
9188         enum ndr_err_code ndr_err;
9189         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9190                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9191         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9192                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9193         }
9194         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9195 }
9196
9197 /*******************************************************************
9198  ********************************************************************/
9199
9200 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9201                              struct spoolss_PortData2 *port2,
9202                              const DATA_BLOB *buf)
9203 {
9204         enum ndr_err_code ndr_err;
9205         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9206                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9207         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9208                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9209         }
9210         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9211 }
9212
9213 /*******************************************************************
9214  Create a new TCP/IP port
9215 *******************************************************************/
9216
9217 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9218                              NT_USER_TOKEN *token, DATA_BLOB *in,
9219                              DATA_BLOB *out, uint32_t *needed)
9220 {
9221         struct spoolss_PortData1 port1;
9222         struct spoolss_PortData2 port2;
9223         char *device_uri = NULL;
9224         uint32_t version;
9225
9226         const char *portname;
9227         const char *hostaddress;
9228         const char *queue;
9229         uint32_t port_number;
9230         uint32_t protocol;
9231
9232         /* peek for spoolss_PortData version */
9233
9234         if (!in || (in->length < (128 + 4))) {
9235                 return WERR_GENERAL_FAILURE;
9236         }
9237
9238         version = IVAL(in->data, 128);
9239
9240         switch (version) {
9241                 case 1:
9242                         ZERO_STRUCT(port1);
9243
9244                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9245                                 return WERR_NOMEM;
9246                         }
9247
9248                         portname        = port1.portname;
9249                         hostaddress     = port1.hostaddress;
9250                         queue           = port1.queue;
9251                         protocol        = port1.protocol;
9252                         port_number     = port1.port_number;
9253
9254                         break;
9255                 case 2:
9256                         ZERO_STRUCT(port2);
9257
9258                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9259                                 return WERR_NOMEM;
9260                         }
9261
9262                         portname        = port2.portname;
9263                         hostaddress     = port2.hostaddress;
9264                         queue           = port2.queue;
9265                         protocol        = port2.protocol;
9266                         port_number     = port2.port_number;
9267
9268                         break;
9269                 default:
9270                         DEBUG(1,("xcvtcp_addport: "
9271                                 "unknown version of port_data: %d\n", version));
9272                         return WERR_UNKNOWN_PORT;
9273         }
9274
9275         /* create the device URI and call the add_port_hook() */
9276
9277         switch (protocol) {
9278         case PROTOCOL_RAWTCP_TYPE:
9279                 device_uri = talloc_asprintf(mem_ctx,
9280                                 "socket://%s:%d/", hostaddress,
9281                                 port_number);
9282                 break;
9283
9284         case PROTOCOL_LPR_TYPE:
9285                 device_uri = talloc_asprintf(mem_ctx,
9286                         "lpr://%s/%s", hostaddress, queue );
9287                 break;
9288
9289         default:
9290                 return WERR_UNKNOWN_PORT;
9291         }
9292
9293         if (!device_uri) {
9294                 return WERR_NOMEM;
9295         }
9296
9297         return add_port_hook(mem_ctx, token, portname, device_uri);
9298 }
9299
9300 /*******************************************************************
9301 *******************************************************************/
9302
9303 struct xcv_api_table xcvtcp_cmds[] = {
9304         { "MonitorUI",  xcvtcp_monitorui },
9305         { "AddPort",    xcvtcp_addport},
9306         { NULL,         NULL }
9307 };
9308
9309 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9310                                      NT_USER_TOKEN *token, const char *command,
9311                                      DATA_BLOB *inbuf,
9312                                      DATA_BLOB *outbuf,
9313                                      uint32_t *needed )
9314 {
9315         int i;
9316
9317         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9318
9319         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9320                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9321                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9322         }
9323
9324         return WERR_BADFUNC;
9325 }
9326
9327 /*******************************************************************
9328 *******************************************************************/
9329 #if 0   /* don't support management using the "Local Port" monitor */
9330
9331 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9332                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9333                                  DATA_BLOB *out, uint32_t *needed)
9334 {
9335         const char *dllname = "localui.dll";
9336
9337         *needed = (strlen(dllname)+1) * 2;
9338
9339         if (out->length < *needed) {
9340                 return WERR_INSUFFICIENT_BUFFER;
9341         }
9342
9343         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9344                 return WERR_NOMEM;
9345         }
9346
9347         return WERR_OK;
9348 }
9349
9350 /*******************************************************************
9351 *******************************************************************/
9352
9353 struct xcv_api_table xcvlocal_cmds[] = {
9354         { "MonitorUI",  xcvlocal_monitorui },
9355         { NULL,         NULL }
9356 };
9357 #else
9358 struct xcv_api_table xcvlocal_cmds[] = {
9359         { NULL,         NULL }
9360 };
9361 #endif
9362
9363
9364
9365 /*******************************************************************
9366 *******************************************************************/
9367
9368 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9369                                        NT_USER_TOKEN *token, const char *command,
9370                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9371                                        uint32_t *needed)
9372 {
9373         int i;
9374
9375         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9376
9377         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9378                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9379                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9380         }
9381         return WERR_BADFUNC;
9382 }
9383
9384 /****************************************************************
9385  _spoolss_XcvData
9386 ****************************************************************/
9387
9388 WERROR _spoolss_XcvData(struct pipes_struct *p,
9389                         struct spoolss_XcvData *r)
9390 {
9391         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9392         DATA_BLOB out_data = data_blob_null;
9393         WERROR werror;
9394
9395         if (!Printer) {
9396                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9397                         OUR_HANDLE(r->in.handle)));
9398                 return WERR_BADFID;
9399         }
9400
9401         /* Has to be a handle to the TCP/IP port monitor */
9402
9403         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9404                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9405                 return WERR_BADFID;
9406         }
9407
9408         /* requires administrative access to the server */
9409
9410         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9411                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9412                 return WERR_ACCESS_DENIED;
9413         }
9414
9415         /* Allocate the outgoing buffer */
9416
9417         if (r->in.out_data_size) {
9418                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9419                 if (out_data.data == NULL) {
9420                         return WERR_NOMEM;
9421                 }
9422         }
9423
9424         switch ( Printer->printer_type ) {
9425         case SPLHND_PORTMON_TCP:
9426                 werror = process_xcvtcp_command(p->mem_ctx,
9427                                                 p->server_info->ptok,
9428                                                 r->in.function_name,
9429                                                 &r->in.in_data, &out_data,
9430                                                 r->out.needed);
9431                 break;
9432         case SPLHND_PORTMON_LOCAL:
9433                 werror = process_xcvlocal_command(p->mem_ctx,
9434                                                   p->server_info->ptok,
9435                                                   r->in.function_name,
9436                                                   &r->in.in_data, &out_data,
9437                                                   r->out.needed);
9438                 break;
9439         default:
9440                 werror = WERR_INVALID_PRINT_MONITOR;
9441         }
9442
9443         if (!W_ERROR_IS_OK(werror)) {
9444                 return werror;
9445         }
9446
9447         *r->out.status_code = 0;
9448
9449         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9450                 memcpy(r->out.out_data, out_data.data,
9451                         MIN(r->in.out_data_size, out_data.length));
9452         }
9453
9454         return WERR_OK;
9455 }
9456
9457 /****************************************************************
9458  _spoolss_AddPrintProcessor
9459 ****************************************************************/
9460
9461 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9462                                   struct spoolss_AddPrintProcessor *r)
9463 {
9464         /* for now, just indicate success and ignore the add.  We'll
9465            automatically set the winprint processor for printer
9466            entries later.  Used to debug the LexMark Optra S 1855 PCL
9467            driver --jerry */
9468
9469         return WERR_OK;
9470 }
9471
9472 /****************************************************************
9473  _spoolss_AddPort
9474 ****************************************************************/
9475
9476 WERROR _spoolss_AddPort(struct pipes_struct *p,
9477                         struct spoolss_AddPort *r)
9478 {
9479         /* do what w2k3 does */
9480
9481         return WERR_NOT_SUPPORTED;
9482 }
9483
9484 /****************************************************************
9485  _spoolss_GetPrinterDriver
9486 ****************************************************************/
9487
9488 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9489                                  struct spoolss_GetPrinterDriver *r)
9490 {
9491         p->rng_fault_state = true;
9492         return WERR_NOT_SUPPORTED;
9493 }
9494
9495 /****************************************************************
9496  _spoolss_ReadPrinter
9497 ****************************************************************/
9498
9499 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9500                             struct spoolss_ReadPrinter *r)
9501 {
9502         p->rng_fault_state = true;
9503         return WERR_NOT_SUPPORTED;
9504 }
9505
9506 /****************************************************************
9507  _spoolss_WaitForPrinterChange
9508 ****************************************************************/
9509
9510 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9511                                      struct spoolss_WaitForPrinterChange *r)
9512 {
9513         p->rng_fault_state = true;
9514         return WERR_NOT_SUPPORTED;
9515 }
9516
9517 /****************************************************************
9518  _spoolss_ConfigurePort
9519 ****************************************************************/
9520
9521 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9522                               struct spoolss_ConfigurePort *r)
9523 {
9524         p->rng_fault_state = true;
9525         return WERR_NOT_SUPPORTED;
9526 }
9527
9528 /****************************************************************
9529  _spoolss_DeletePort
9530 ****************************************************************/
9531
9532 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9533                            struct spoolss_DeletePort *r)
9534 {
9535         p->rng_fault_state = true;
9536         return WERR_NOT_SUPPORTED;
9537 }
9538
9539 /****************************************************************
9540  _spoolss_CreatePrinterIC
9541 ****************************************************************/
9542
9543 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9544                                 struct spoolss_CreatePrinterIC *r)
9545 {
9546         p->rng_fault_state = true;
9547         return WERR_NOT_SUPPORTED;
9548 }
9549
9550 /****************************************************************
9551  _spoolss_PlayGDIScriptOnPrinterIC
9552 ****************************************************************/
9553
9554 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9555                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9556 {
9557         p->rng_fault_state = true;
9558         return WERR_NOT_SUPPORTED;
9559 }
9560
9561 /****************************************************************
9562  _spoolss_DeletePrinterIC
9563 ****************************************************************/
9564
9565 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9566                                 struct spoolss_DeletePrinterIC *r)
9567 {
9568         p->rng_fault_state = true;
9569         return WERR_NOT_SUPPORTED;
9570 }
9571
9572 /****************************************************************
9573  _spoolss_AddPrinterConnection
9574 ****************************************************************/
9575
9576 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9577                                      struct spoolss_AddPrinterConnection *r)
9578 {
9579         p->rng_fault_state = true;
9580         return WERR_NOT_SUPPORTED;
9581 }
9582
9583 /****************************************************************
9584  _spoolss_DeletePrinterConnection
9585 ****************************************************************/
9586
9587 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9588                                         struct spoolss_DeletePrinterConnection *r)
9589 {
9590         p->rng_fault_state = true;
9591         return WERR_NOT_SUPPORTED;
9592 }
9593
9594 /****************************************************************
9595  _spoolss_PrinterMessageBox
9596 ****************************************************************/
9597
9598 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9599                                   struct spoolss_PrinterMessageBox *r)
9600 {
9601         p->rng_fault_state = true;
9602         return WERR_NOT_SUPPORTED;
9603 }
9604
9605 /****************************************************************
9606  _spoolss_AddMonitor
9607 ****************************************************************/
9608
9609 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9610                            struct spoolss_AddMonitor *r)
9611 {
9612         p->rng_fault_state = true;
9613         return WERR_NOT_SUPPORTED;
9614 }
9615
9616 /****************************************************************
9617  _spoolss_DeleteMonitor
9618 ****************************************************************/
9619
9620 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
9621                               struct spoolss_DeleteMonitor *r)
9622 {
9623         p->rng_fault_state = true;
9624         return WERR_NOT_SUPPORTED;
9625 }
9626
9627 /****************************************************************
9628  _spoolss_DeletePrintProcessor
9629 ****************************************************************/
9630
9631 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
9632                                      struct spoolss_DeletePrintProcessor *r)
9633 {
9634         p->rng_fault_state = true;
9635         return WERR_NOT_SUPPORTED;
9636 }
9637
9638 /****************************************************************
9639  _spoolss_AddPrintProvidor
9640 ****************************************************************/
9641
9642 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
9643                                  struct spoolss_AddPrintProvidor *r)
9644 {
9645         p->rng_fault_state = true;
9646         return WERR_NOT_SUPPORTED;
9647 }
9648
9649 /****************************************************************
9650  _spoolss_DeletePrintProvidor
9651 ****************************************************************/
9652
9653 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
9654                                     struct spoolss_DeletePrintProvidor *r)
9655 {
9656         p->rng_fault_state = true;
9657         return WERR_NOT_SUPPORTED;
9658 }
9659
9660 /****************************************************************
9661  _spoolss_FindFirstPrinterChangeNotification
9662 ****************************************************************/
9663
9664 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
9665                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9666 {
9667         p->rng_fault_state = true;
9668         return WERR_NOT_SUPPORTED;
9669 }
9670
9671 /****************************************************************
9672  _spoolss_FindNextPrinterChangeNotification
9673 ****************************************************************/
9674
9675 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
9676                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9677 {
9678         p->rng_fault_state = true;
9679         return WERR_NOT_SUPPORTED;
9680 }
9681
9682 /****************************************************************
9683  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9684 ****************************************************************/
9685
9686 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
9687                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9688 {
9689         p->rng_fault_state = true;
9690         return WERR_NOT_SUPPORTED;
9691 }
9692
9693 /****************************************************************
9694  _spoolss_ReplyOpenPrinter
9695 ****************************************************************/
9696
9697 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
9698                                  struct spoolss_ReplyOpenPrinter *r)
9699 {
9700         p->rng_fault_state = true;
9701         return WERR_NOT_SUPPORTED;
9702 }
9703
9704 /****************************************************************
9705  _spoolss_RouterReplyPrinter
9706 ****************************************************************/
9707
9708 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
9709                                    struct spoolss_RouterReplyPrinter *r)
9710 {
9711         p->rng_fault_state = true;
9712         return WERR_NOT_SUPPORTED;
9713 }
9714
9715 /****************************************************************
9716  _spoolss_ReplyClosePrinter
9717 ****************************************************************/
9718
9719 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
9720                                   struct spoolss_ReplyClosePrinter *r)
9721 {
9722         p->rng_fault_state = true;
9723         return WERR_NOT_SUPPORTED;
9724 }
9725
9726 /****************************************************************
9727  _spoolss_AddPortEx
9728 ****************************************************************/
9729
9730 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
9731                           struct spoolss_AddPortEx *r)
9732 {
9733         p->rng_fault_state = true;
9734         return WERR_NOT_SUPPORTED;
9735 }
9736
9737 /****************************************************************
9738  _spoolss_RouterFindFirstPrinterChangeNotification
9739 ****************************************************************/
9740
9741 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
9742                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9743 {
9744         p->rng_fault_state = true;
9745         return WERR_NOT_SUPPORTED;
9746 }
9747
9748 /****************************************************************
9749  _spoolss_SpoolerInit
9750 ****************************************************************/
9751
9752 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
9753                             struct spoolss_SpoolerInit *r)
9754 {
9755         p->rng_fault_state = true;
9756         return WERR_NOT_SUPPORTED;
9757 }
9758
9759 /****************************************************************
9760  _spoolss_ResetPrinterEx
9761 ****************************************************************/
9762
9763 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
9764                                struct spoolss_ResetPrinterEx *r)
9765 {
9766         p->rng_fault_state = true;
9767         return WERR_NOT_SUPPORTED;
9768 }
9769
9770 /****************************************************************
9771  _spoolss_RouterReplyPrinterEx
9772 ****************************************************************/
9773
9774 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
9775                                      struct spoolss_RouterReplyPrinterEx *r)
9776 {
9777         p->rng_fault_state = true;
9778         return WERR_NOT_SUPPORTED;
9779 }
9780
9781 /****************************************************************
9782  _spoolss_44
9783 ****************************************************************/
9784
9785 WERROR _spoolss_44(struct pipes_struct *p,
9786                    struct spoolss_44 *r)
9787 {
9788         p->rng_fault_state = true;
9789         return WERR_NOT_SUPPORTED;
9790 }
9791
9792 /****************************************************************
9793  _spoolss_47
9794 ****************************************************************/
9795
9796 WERROR _spoolss_47(struct pipes_struct *p,
9797                    struct spoolss_47 *r)
9798 {
9799         p->rng_fault_state = true;
9800         return WERR_NOT_SUPPORTED;
9801 }
9802
9803 /****************************************************************
9804  _spoolss_4a
9805 ****************************************************************/
9806
9807 WERROR _spoolss_4a(struct pipes_struct *p,
9808                    struct spoolss_4a *r)
9809 {
9810         p->rng_fault_state = true;
9811         return WERR_NOT_SUPPORTED;
9812 }
9813
9814 /****************************************************************
9815  _spoolss_4b
9816 ****************************************************************/
9817
9818 WERROR _spoolss_4b(struct pipes_struct *p,
9819                    struct spoolss_4b *r)
9820 {
9821         p->rng_fault_state = true;
9822         return WERR_NOT_SUPPORTED;
9823 }
9824
9825 /****************************************************************
9826  _spoolss_4c
9827 ****************************************************************/
9828
9829 WERROR _spoolss_4c(struct pipes_struct *p,
9830                    struct spoolss_4c *r)
9831 {
9832         p->rng_fault_state = true;
9833         return WERR_NOT_SUPPORTED;
9834 }
9835
9836 /****************************************************************
9837  _spoolss_53
9838 ****************************************************************/
9839
9840 WERROR _spoolss_53(struct pipes_struct *p,
9841                    struct spoolss_53 *r)
9842 {
9843         p->rng_fault_state = true;
9844         return WERR_NOT_SUPPORTED;
9845 }
9846
9847 /****************************************************************
9848  _spoolss_55
9849 ****************************************************************/
9850
9851 WERROR _spoolss_55(struct pipes_struct *p,
9852                    struct spoolss_55 *r)
9853 {
9854         p->rng_fault_state = true;
9855         return WERR_NOT_SUPPORTED;
9856 }
9857
9858 /****************************************************************
9859  _spoolss_56
9860 ****************************************************************/
9861
9862 WERROR _spoolss_56(struct pipes_struct *p,
9863                    struct spoolss_56 *r)
9864 {
9865         p->rng_fault_state = true;
9866         return WERR_NOT_SUPPORTED;
9867 }
9868
9869 /****************************************************************
9870  _spoolss_57
9871 ****************************************************************/
9872
9873 WERROR _spoolss_57(struct pipes_struct *p,
9874                    struct spoolss_57 *r)
9875 {
9876         p->rng_fault_state = true;
9877         return WERR_NOT_SUPPORTED;
9878 }
9879
9880 /****************************************************************
9881  _spoolss_5a
9882 ****************************************************************/
9883
9884 WERROR _spoolss_5a(struct pipes_struct *p,
9885                    struct spoolss_5a *r)
9886 {
9887         p->rng_fault_state = true;
9888         return WERR_NOT_SUPPORTED;
9889 }
9890
9891 /****************************************************************
9892  _spoolss_5b
9893 ****************************************************************/
9894
9895 WERROR _spoolss_5b(struct pipes_struct *p,
9896                    struct spoolss_5b *r)
9897 {
9898         p->rng_fault_state = true;
9899         return WERR_NOT_SUPPORTED;
9900 }
9901
9902 /****************************************************************
9903  _spoolss_5c
9904 ****************************************************************/
9905
9906 WERROR _spoolss_5c(struct pipes_struct *p,
9907                    struct spoolss_5c *r)
9908 {
9909         p->rng_fault_state = true;
9910         return WERR_NOT_SUPPORTED;
9911 }
9912
9913 /****************************************************************
9914  _spoolss_5d
9915 ****************************************************************/
9916
9917 WERROR _spoolss_5d(struct pipes_struct *p,
9918                    struct spoolss_5d *r)
9919 {
9920         p->rng_fault_state = true;
9921         return WERR_NOT_SUPPORTED;
9922 }
9923
9924 /****************************************************************
9925  _spoolss_5e
9926 ****************************************************************/
9927
9928 WERROR _spoolss_5e(struct pipes_struct *p,
9929                    struct spoolss_5e *r)
9930 {
9931         p->rng_fault_state = true;
9932         return WERR_NOT_SUPPORTED;
9933 }
9934
9935 /****************************************************************
9936  _spoolss_5f
9937 ****************************************************************/
9938
9939 WERROR _spoolss_5f(struct pipes_struct *p,
9940                    struct spoolss_5f *r)
9941 {
9942         p->rng_fault_state = true;
9943         return WERR_NOT_SUPPORTED;
9944 }
9945
9946 /****************************************************************
9947  _spoolss_60
9948 ****************************************************************/
9949
9950 WERROR _spoolss_60(struct pipes_struct *p,
9951                    struct spoolss_60 *r)
9952 {
9953         p->rng_fault_state = true;
9954         return WERR_NOT_SUPPORTED;
9955 }
9956
9957 /****************************************************************
9958  _spoolss_61
9959 ****************************************************************/
9960
9961 WERROR _spoolss_61(struct pipes_struct *p,
9962                    struct spoolss_61 *r)
9963 {
9964         p->rng_fault_state = true;
9965         return WERR_NOT_SUPPORTED;
9966 }
9967
9968 /****************************************************************
9969  _spoolss_62
9970 ****************************************************************/
9971
9972 WERROR _spoolss_62(struct pipes_struct *p,
9973                    struct spoolss_62 *r)
9974 {
9975         p->rng_fault_state = true;
9976         return WERR_NOT_SUPPORTED;
9977 }
9978
9979 /****************************************************************
9980  _spoolss_63
9981 ****************************************************************/
9982
9983 WERROR _spoolss_63(struct pipes_struct *p,
9984                    struct spoolss_63 *r)
9985 {
9986         p->rng_fault_state = true;
9987         return WERR_NOT_SUPPORTED;
9988 }
9989
9990 /****************************************************************
9991  _spoolss_64
9992 ****************************************************************/
9993
9994 WERROR _spoolss_64(struct pipes_struct *p,
9995                    struct spoolss_64 *r)
9996 {
9997         p->rng_fault_state = true;
9998         return WERR_NOT_SUPPORTED;
9999 }
10000
10001 /****************************************************************
10002  _spoolss_65
10003 ****************************************************************/
10004
10005 WERROR _spoolss_65(struct pipes_struct *p,
10006                    struct spoolss_65 *r)
10007 {
10008         p->rng_fault_state = true;
10009         return WERR_NOT_SUPPORTED;
10010 }
10011
10012 /****************************************************************
10013  _spoolss_GetCorePrinterDrivers
10014 ****************************************************************/
10015
10016 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10017                                       struct spoolss_GetCorePrinterDrivers *r)
10018 {
10019         p->rng_fault_state = true;
10020         return WERR_NOT_SUPPORTED;
10021 }
10022
10023 /****************************************************************
10024  _spoolss_67
10025 ****************************************************************/
10026
10027 WERROR _spoolss_67(struct pipes_struct *p,
10028                    struct spoolss_67 *r)
10029 {
10030         p->rng_fault_state = true;
10031         return WERR_NOT_SUPPORTED;
10032 }
10033
10034 /****************************************************************
10035  _spoolss_GetPrinterDriverPackagePath
10036 ****************************************************************/
10037
10038 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10039                                             struct spoolss_GetPrinterDriverPackagePath *r)
10040 {
10041         p->rng_fault_state = true;
10042         return WERR_NOT_SUPPORTED;
10043 }
10044
10045 /****************************************************************
10046  _spoolss_69
10047 ****************************************************************/
10048
10049 WERROR _spoolss_69(struct pipes_struct *p,
10050                    struct spoolss_69 *r)
10051 {
10052         p->rng_fault_state = true;
10053         return WERR_NOT_SUPPORTED;
10054 }
10055
10056 /****************************************************************
10057  _spoolss_6a
10058 ****************************************************************/
10059
10060 WERROR _spoolss_6a(struct pipes_struct *p,
10061                    struct spoolss_6a *r)
10062 {
10063         p->rng_fault_state = true;
10064         return WERR_NOT_SUPPORTED;
10065 }
10066
10067 /****************************************************************
10068  _spoolss_6b
10069 ****************************************************************/
10070
10071 WERROR _spoolss_6b(struct pipes_struct *p,
10072                    struct spoolss_6b *r)
10073 {
10074         p->rng_fault_state = true;
10075         return WERR_NOT_SUPPORTED;
10076 }
10077
10078 /****************************************************************
10079  _spoolss_6c
10080 ****************************************************************/
10081
10082 WERROR _spoolss_6c(struct pipes_struct *p,
10083                    struct spoolss_6c *r)
10084 {
10085         p->rng_fault_state = true;
10086         return WERR_NOT_SUPPORTED;
10087 }
10088
10089 /****************************************************************
10090  _spoolss_6d
10091 ****************************************************************/
10092
10093 WERROR _spoolss_6d(struct pipes_struct *p,
10094                    struct spoolss_6d *r)
10095 {
10096         p->rng_fault_state = true;
10097         return WERR_NOT_SUPPORTED;
10098 }