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