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