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