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