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