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