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