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