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