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