s3-spoolss: use pidl for _spoolss_GetPrinterDriver2.
[metze/samba/wip.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  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32         ((info)?ndr_size_##fn(info, level, ic, 0):0)
33
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
36
37 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
38
39
40 extern userdom_struct current_user_info;
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_RPC_SRV
44
45 #ifndef MAX_OPEN_PRINTER_EXS
46 #define MAX_OPEN_PRINTER_EXS 50
47 #endif
48
49 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
50 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
51
52 struct table_node {
53         const char    *long_archi;
54         const char    *short_archi;
55         int     version;
56 };
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32 counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32 smb_connections=0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected==True) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected=False;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
231 {
232         Printer_entry *find_printer = NULL;
233
234         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
235                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
236                 return NULL;
237         }
238
239         return find_printer;
240 }
241
242 /****************************************************************************
243  Close printer index by handle.
244 ****************************************************************************/
245
246 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
247 {
248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249
250         if (!Printer) {
251                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
252                 return False;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return True;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
265 {
266         char *cmd = lp_deleteprinter_cmd();
267         char *command = NULL;
268         int ret;
269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
270         bool is_print_op = False;
271
272         /* can't fail if we don't try */
273
274         if ( !*cmd )
275                 return WERR_OK;
276
277         command = talloc_asprintf(ctx,
278                         "%s \"%s\"",
279                         cmd, sharename);
280         if (!command) {
281                 return WERR_NOMEM;
282         }
283         if ( token )
284                 is_print_op = user_has_privileges( token, &se_printop );
285
286         DEBUG(10,("Running [%s]\n", command));
287
288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290         if ( is_print_op )
291                 become_root();
292
293         if ( (ret = smbrun(command, NULL)) == 0 ) {
294                 /* Tell everyone we updated smb.conf. */
295                 message_send_all(smbd_messaging_context(),
296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
297         }
298
299         if ( is_print_op )
300                 unbecome_root();
301
302         /********** END SePrintOperatorPrivlege BLOCK **********/
303
304         DEBUGADD(10,("returned [%d]\n", ret));
305
306         TALLOC_FREE(command);
307
308         if (ret != 0)
309                 return WERR_BADFID; /* What to return here? */
310
311         /* go ahead and re-read the services immediately */
312         reload_services( False );
313
314         if ( lp_servicenumber( sharename )  < 0 )
315                 return WERR_ACCESS_DENIED;
316
317         return WERR_OK;
318 }
319
320 /****************************************************************************
321  Delete a printer given a handle.
322 ****************************************************************************/
323
324 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
325 {
326         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
327
328         if (!Printer) {
329                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
330                 return WERR_BADFID;
331         }
332
333         /*
334          * It turns out that Windows allows delete printer on a handle
335          * opened by an admin user, then used on a pipe handle created
336          * by an anonymous user..... but they're working on security.... riiight !
337          * JRA.
338          */
339
340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
341                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
342                 return WERR_ACCESS_DENIED;
343         }
344
345         /* this does not need a become root since the access check has been
346            done on the handle already */
347
348         if (del_a_printer( Printer->sharename ) != 0) {
349                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
350                 return WERR_BADFID;
351         }
352
353         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
354                                    Printer->sharename );
355 }
356
357 /****************************************************************************
358  Return the snum of a printer corresponding to an handle.
359 ****************************************************************************/
360
361 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
362                              struct share_params **params)
363 {
364         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368                 return False;
369         }
370
371         switch (Printer->printer_type) {
372                 case SPLHND_PRINTER:
373                         DEBUG(4,("short name:%s\n", Printer->sharename));
374                         *number = print_queue_snum(Printer->sharename);
375                         return (*number != -1);
376                 case SPLHND_SERVER:
377                         return False;
378                 default:
379                         return False;
380         }
381 }
382
383 /****************************************************************************
384  Set printer handle type.
385  Check if it's \\server or \\server\printer
386 ****************************************************************************/
387
388 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
389 {
390         DEBUG(3,("Setting printer type=%s\n", handlename));
391
392         if ( strlen(handlename) < 3 ) {
393                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
394                 return False;
395         }
396
397         /* it's a print server */
398         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
399                 DEBUGADD(4,("Printer is a print server\n"));
400                 Printer->printer_type = SPLHND_SERVER;
401         }
402         /* it's a printer (set_printer_hnd_name() will handle port monitors */
403         else {
404                 DEBUGADD(4,("Printer is a printer\n"));
405                 Printer->printer_type = SPLHND_PRINTER;
406         }
407
408         return True;
409 }
410
411 /****************************************************************************
412  Set printer handle name..  Accept names like \\server, \\server\printer,
413  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
414  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
415  XcvDataPort() interface.
416 ****************************************************************************/
417
418 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
419 {
420         int snum;
421         int n_services=lp_numservices();
422         char *aprinter, *printername;
423         const char *servername;
424         fstring sname;
425         bool found=False;
426         NT_PRINTER_INFO_LEVEL *printer = NULL;
427         WERROR result;
428
429         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
430
431         aprinter = handlename;
432         if ( *handlename == '\\' ) {
433                 servername = canon_servername(handlename);
434                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
435                         *aprinter = '\0';
436                         aprinter++;
437                 }
438         } else {
439                 servername = "";
440         }
441
442         /* save the servername to fill in replies on this handle */
443
444         if ( !is_myname_or_ipaddr( servername ) )
445                 return False;
446
447         fstrcpy( Printer->servername, servername );
448
449         if ( Printer->printer_type == SPLHND_SERVER )
450                 return True;
451
452         if ( Printer->printer_type != SPLHND_PRINTER )
453                 return False;
454
455         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
456
457         /* check for the Port Monitor Interface */
458
459         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
460                 Printer->printer_type = SPLHND_PORTMON_TCP;
461                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
462                 found = True;
463         }
464         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
465                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
466                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
467                 found = True;
468         }
469
470         /* Search all sharenames first as this is easier than pulling
471            the printer_info_2 off of disk. Don't use find_service() since
472            that calls out to map_username() */
473
474         /* do another loop to look for printernames */
475
476         for (snum=0; !found && snum<n_services; snum++) {
477
478                 /* no point going on if this is not a printer */
479
480                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
481                         continue;
482
483                 fstrcpy(sname, lp_servicename(snum));
484                 if ( strequal( aprinter, sname ) ) {
485                         found = True;
486                         break;
487                 }
488
489                 /* no point looking up the printer object if
490                    we aren't allowing printername != sharename */
491
492                 if ( lp_force_printername(snum) )
493                         continue;
494
495                 fstrcpy(sname, lp_servicename(snum));
496
497                 printer = NULL;
498
499                 /* This call doesn't fill in the location or comment from
500                  * a CUPS server for efficiency with large numbers of printers.
501                  * JRA.
502                  */
503
504                 result = get_a_printer_search( NULL, &printer, 2, sname );
505                 if ( !W_ERROR_IS_OK(result) ) {
506                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
507                                 sname, win_errstr(result)));
508                         continue;
509                 }
510
511                 /* printername is always returned as \\server\printername */
512                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
513                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
514                                 printer->info_2->printername));
515                         free_a_printer( &printer, 2);
516                         continue;
517                 }
518
519                 printername++;
520
521                 if ( strequal(printername, aprinter) ) {
522                         free_a_printer( &printer, 2);
523                         found = True;
524                         break;
525                 }
526
527                 DEBUGADD(10, ("printername: %s\n", printername));
528
529                 free_a_printer( &printer, 2);
530         }
531
532         free_a_printer( &printer, 2);
533
534         if ( !found ) {
535                 DEBUGADD(4,("Printer not found\n"));
536                 return False;
537         }
538
539         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
540
541         fstrcpy(Printer->sharename, sname);
542
543         return True;
544 }
545
546 /****************************************************************************
547  Find first available printer slot. creates a printer handle for you.
548  ****************************************************************************/
549
550 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
551 {
552         Printer_entry *new_printer;
553
554         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
555
556         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
557         if (new_printer == NULL) {
558                 return false;
559         }
560         talloc_set_destructor(new_printer, printer_entry_destructor);
561
562         if (!create_policy_hnd(p, hnd, new_printer)) {
563                 TALLOC_FREE(new_printer);
564                 return False;
565         }
566
567         /* Add to the internal list. */
568         DLIST_ADD(printers_list, new_printer);
569
570         new_printer->notify.option=NULL;
571
572         if (!set_printer_hnd_printertype(new_printer, name)) {
573                 close_printer_handle(p, hnd);
574                 return False;
575         }
576
577         if (!set_printer_hnd_name(new_printer, name)) {
578                 close_printer_handle(p, hnd);
579                 return False;
580         }
581
582         new_printer->access_granted = access_granted;
583
584         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585
586         return True;
587 }
588
589 /***************************************************************************
590  check to see if the client motify handle is monitoring the notification
591  given by (notify_type, notify_field).
592  **************************************************************************/
593
594 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
595                                       uint16 notify_field)
596 {
597         return True;
598 }
599
600 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
601                                 uint16 notify_field)
602 {
603         struct spoolss_NotifyOption *option = p->notify.option;
604         uint32 i, j;
605
606         /*
607          * Flags should always be zero when the change notify
608          * is registered by the client's spooler.  A user Win32 app
609          * might use the flags though instead of the NOTIFY_OPTION_INFO
610          * --jerry
611          */
612
613         if (!option) {
614                 return False;
615         }
616
617         if (p->notify.flags)
618                 return is_monitoring_event_flags(
619                         p->notify.flags, notify_type, notify_field);
620
621         for (i = 0; i < option->count; i++) {
622
623                 /* Check match for notify_type */
624
625                 if (option->types[i].type != notify_type)
626                         continue;
627
628                 /* Check match for field */
629
630                 for (j = 0; j < option->types[i].count; j++) {
631                         if (option->types[i].fields[j] == notify_field) {
632                                 return True;
633                         }
634                 }
635         }
636
637         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
638                    p->servername, p->sharename, notify_type, notify_field));
639
640         return False;
641 }
642
643 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
644         _data->data.integer[0] = _integer; \
645         _data->data.integer[1] = 0;
646
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
649         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
650         if (!_data->data.string.string) {\
651                 _data->data.string.size = 0; \
652         } \
653         _data->data.string.size = strlen_m_term(_p) * 2;
654
655 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
656         _data->data.devmode.devmode = _devmode;
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
659         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
660         if (!_data->data.sd.sd) { \
661                 _data->data.sd.sd_size = 0; \
662         } \
663         _data->data.sd.sd_size = _size;
664
665 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
666                                    struct tm *t,
667                                    const char **pp,
668                                    uint32_t *plen)
669 {
670         struct spoolss_Time st;
671         uint32_t len = 16;
672         char *p;
673
674         if (!init_systemtime(&st, t)) {
675                 return;
676         }
677
678         p = talloc_array(mem_ctx, char, len);
679         if (!p) {
680                 return;
681         }
682
683         /*
684          * Systemtime must be linearized as a set of UINT16's.
685          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
686          */
687
688         SSVAL(p, 0, st.year);
689         SSVAL(p, 2, st.month);
690         SSVAL(p, 4, st.day_of_week);
691         SSVAL(p, 6, st.day);
692         SSVAL(p, 8, st.hour);
693         SSVAL(p, 10, st.minute);
694         SSVAL(p, 12, st.second);
695         SSVAL(p, 14, st.millisecond);
696
697         *pp = p;
698         *plen = len;
699 }
700
701 /* Convert a notification message to a struct spoolss_Notify */
702
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704                              struct spoolss_Notify *data,
705                              TALLOC_CTX *mem_ctx)
706 {
707         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
708 }
709
710 static void notify_string(struct spoolss_notify_msg *msg,
711                           struct spoolss_Notify *data,
712                           TALLOC_CTX *mem_ctx)
713 {
714         /* The length of the message includes the trailing \0 */
715
716         data->data.string.size = msg->len * 2;
717         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
718         if (!data->data.string.string) {
719                 data->data.string.size = 0;
720                 return;
721         }
722 }
723
724 static void notify_system_time(struct spoolss_notify_msg *msg,
725                                struct spoolss_Notify *data,
726                                TALLOC_CTX *mem_ctx)
727 {
728         data->data.string.string = NULL;
729         data->data.string.size = 0;
730
731         if (msg->len != sizeof(time_t)) {
732                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
733                           msg->len));
734                 return;
735         }
736
737         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
738                                &data->data.string.string,
739                                &data->data.string.size);
740 }
741
742 struct notify2_message_table {
743         const char *name;
744         void (*fn)(struct spoolss_notify_msg *msg,
745                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
746 };
747
748 static struct notify2_message_table printer_notify_table[] = {
749         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
750         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
751         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
752         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
753         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
754         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
755         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
756         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
757         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
758         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
759         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
760         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
761         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
762         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
763         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
764         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
765         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
766         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
767         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 };
769
770 static struct notify2_message_table job_notify_table[] = {
771         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
772         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
773         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
774         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
775         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
776         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
777         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
778         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
779         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
780         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
781         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
782         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
783         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
784         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
785         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
786         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
787         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
788         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
789         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
790         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
791         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
792         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
793         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
794         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
795 };
796
797
798 /***********************************************************************
799  Allocate talloc context for container object
800  **********************************************************************/
801
802 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 {
804         if ( !ctr )
805                 return;
806
807         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808
809         return;
810 }
811
812 /***********************************************************************
813  release all allocated memory and zero out structure
814  **********************************************************************/
815
816 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
817 {
818         if ( !ctr )
819                 return;
820
821         if ( ctr->ctx )
822                 talloc_destroy(ctr->ctx);
823
824         ZERO_STRUCTP(ctr);
825
826         return;
827 }
828
829 /***********************************************************************
830  **********************************************************************/
831
832 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 {
834         if ( !ctr )
835                 return NULL;
836
837         return ctr->ctx;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 {
845         if ( !ctr || !ctr->msg_groups )
846                 return NULL;
847
848         if ( idx >= ctr->num_groups )
849                 return NULL;
850
851         return &ctr->msg_groups[idx];
852
853 }
854
855 /***********************************************************************
856  How many groups of change messages do we have ?
857  **********************************************************************/
858
859 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 {
861         if ( !ctr )
862                 return 0;
863
864         return ctr->num_groups;
865 }
866
867 /***********************************************************************
868  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
869  **********************************************************************/
870
871 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 {
873         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
874         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
875         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
876         int                             i, new_slot;
877
878         if ( !ctr || !msg )
879                 return 0;
880
881         /* loop over all groups looking for a matching printer name */
882
883         for ( i=0; i<ctr->num_groups; i++ ) {
884                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
885                         break;
886         }
887
888         /* add a new group? */
889
890         if ( i == ctr->num_groups ) {
891                 ctr->num_groups++;
892
893                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
894                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895                         return 0;
896                 }
897                 ctr->msg_groups = groups;
898
899                 /* clear the new entry and set the printer name */
900
901                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
902                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903         }
904
905         /* add the change messages; 'i' is the correct index now regardless */
906
907         msg_grp = &ctr->msg_groups[i];
908
909         msg_grp->num_msgs++;
910
911         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
912                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913                 return 0;
914         }
915         msg_grp->msgs = msg_list;
916
917         new_slot = msg_grp->num_msgs-1;
918         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919
920         /* need to allocate own copy of data */
921
922         if ( msg->len != 0 )
923                 msg_grp->msgs[new_slot].notify.data = (char *)
924                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
925
926         return ctr->num_groups;
927 }
928
929 /***********************************************************************
930  Send a change notication message on all handles which have a call
931  back registered
932  **********************************************************************/
933
934 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
935 {
936         Printer_entry            *p;
937         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
938         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
939         SPOOLSS_NOTIFY_MSG       *messages;
940         int                      sending_msg_count;
941
942         if ( !msg_group ) {
943                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944                 return;
945         }
946
947         messages = msg_group->msgs;
948
949         if ( !messages ) {
950                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951                 return;
952         }
953
954         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
955
956         /* loop over all printers */
957
958         for (p = printers_list; p; p = p->next) {
959                 struct spoolss_Notify *notifies;
960                 uint32_t count = 0;
961                 uint32_t id;
962                 int     i;
963
964                 /* Is there notification on this handle? */
965
966                 if ( !p->notify.client_connected )
967                         continue;
968
969                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
970
971                 /* For this printer?  Print servers always receive
972                    notifications. */
973
974                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
975                     ( !strequal(msg_group->printername, p->sharename) ) )
976                         continue;
977
978                 DEBUG(10,("Our printer\n"));
979
980                 /* allocate the max entries possible */
981
982                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
983                 if (!notifies) {
984                         return;
985                 }
986
987                 /* build the array of change notifications */
988
989                 sending_msg_count = 0;
990
991                 for ( i=0; i<msg_group->num_msgs; i++ ) {
992                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
993
994                         /* Are we monitoring this event? */
995
996                         if (!is_monitoring_event(p, msg->type, msg->field))
997                                 continue;
998
999                         sending_msg_count++;
1000
1001
1002                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1003                                 msg->type, msg->field, p->sharename));
1004
1005                         /*
1006                          * if the is a printer notification handle and not a job notification
1007                          * type, then set the id to 0.  Other wise just use what was specified
1008                          * in the message.
1009                          *
1010                          * When registering change notification on a print server handle
1011                          * we always need to send back the id (snum) matching the printer
1012                          * for which the change took place.  For change notify registered
1013                          * on a printer handle, this does not matter and the id should be 0.
1014                          *
1015                          * --jerry
1016                          */
1017
1018                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019                                 id = 0;
1020                         else
1021                                 id = msg->id;
1022
1023
1024                         /* Convert unix jobid to smb jobid */
1025
1026                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1027                                 id = sysjob_to_jobid(msg->id);
1028
1029                                 if (id == -1) {
1030                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1031                                         goto done;
1032                                 }
1033                         }
1034
1035                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1036
1037                         switch(msg->type) {
1038                         case PRINTER_NOTIFY_TYPE:
1039                                 if ( printer_notify_table[msg->field].fn )
1040                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1041                                 break;
1042
1043                         case JOB_NOTIFY_TYPE:
1044                                 if ( job_notify_table[msg->field].fn )
1045                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1046                                 break;
1047
1048                         default:
1049                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1050                                 goto done;
1051                         }
1052
1053                         count++;
1054                 }
1055
1056                 if ( sending_msg_count ) {
1057                         NTSTATUS status;
1058                         WERROR werr;
1059                         union spoolss_ReplyPrinterInfo info;
1060                         struct spoolss_NotifyInfo info0;
1061                         uint32_t reply_result;
1062
1063                         info0.version   = 0x2;
1064                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1065                         info0.count     = count;
1066                         info0.notifies  = notifies;
1067
1068                         info.info0 = &info0;
1069
1070                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1071                                                                      &p->notify.client_hnd,
1072                                                                      p->notify.change, /* color */
1073                                                                      p->notify.flags,
1074                                                                      &reply_result,
1075                                                                      0, /* reply_type, must be 0 */
1076                                                                      info,
1077                                                                      &werr);
1078                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1079                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1080                                         notify_cli_pipe->srv_name_slash,
1081                                         win_errstr(werr)));
1082                         }
1083                         switch (reply_result) {
1084                                 case 0:
1085                                         break;
1086                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1087                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1088                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1089                                         break;
1090                                 default:
1091                                         break;
1092                         }
1093                 }
1094         }
1095
1096 done:
1097         DEBUG(8,("send_notify2_changes: Exit...\n"));
1098         return;
1099 }
1100
1101 /***********************************************************************
1102  **********************************************************************/
1103
1104 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1105 {
1106
1107         uint32 tv_sec, tv_usec;
1108         size_t offset = 0;
1109
1110         /* Unpack message */
1111
1112         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1113                              msg->printer);
1114
1115         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1116                                 &tv_sec, &tv_usec,
1117                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1118
1119         if (msg->len == 0)
1120                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1121                            &msg->notify.value[0], &msg->notify.value[1]);
1122         else
1123                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1124                            &msg->len, &msg->notify.data);
1125
1126         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1127                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1128
1129         tv->tv_sec = tv_sec;
1130         tv->tv_usec = tv_usec;
1131
1132         if (msg->len == 0)
1133                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1134                           msg->notify.value[1]));
1135         else
1136                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1137
1138         return True;
1139 }
1140
1141 /********************************************************************
1142  Receive a notify2 message list
1143  ********************************************************************/
1144
1145 static void receive_notify2_message_list(struct messaging_context *msg,
1146                                          void *private_data,
1147                                          uint32_t msg_type,
1148                                          struct server_id server_id,
1149                                          DATA_BLOB *data)
1150 {
1151         size_t                  msg_count, i;
1152         char                    *buf = (char *)data->data;
1153         char                    *msg_ptr;
1154         size_t                  msg_len;
1155         SPOOLSS_NOTIFY_MSG      notify;
1156         SPOOLSS_NOTIFY_MSG_CTR  messages;
1157         int                     num_groups;
1158
1159         if (data->length < 4) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1161                 return;
1162         }
1163
1164         msg_count = IVAL(buf, 0);
1165         msg_ptr = buf + 4;
1166
1167         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168
1169         if (msg_count == 0) {
1170                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1171                 return;
1172         }
1173
1174         /* initialize the container */
1175
1176         ZERO_STRUCT( messages );
1177         notify_msg_ctr_init( &messages );
1178
1179         /*
1180          * build message groups for each printer identified
1181          * in a change_notify msg.  Remember that a PCN message
1182          * includes the handle returned for the srv_spoolss_replyopenprinter()
1183          * call.  Therefore messages are grouped according to printer handle.
1184          */
1185
1186         for ( i=0; i<msg_count; i++ ) {
1187                 struct timeval msg_tv;
1188
1189                 if (msg_ptr + 4 - buf > data->length) {
1190                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1191                         return;
1192                 }
1193
1194                 msg_len = IVAL(msg_ptr,0);
1195                 msg_ptr += 4;
1196
1197                 if (msg_ptr + msg_len - buf > data->length) {
1198                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1199                         return;
1200                 }
1201
1202                 /* unpack messages */
1203
1204                 ZERO_STRUCT( notify );
1205                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1206                 msg_ptr += msg_len;
1207
1208                 /* add to correct list in container */
1209
1210                 notify_msg_ctr_addmsg( &messages, &notify );
1211
1212                 /* free memory that might have been allocated by notify2_unpack_msg() */
1213
1214                 if ( notify.len != 0 )
1215                         SAFE_FREE( notify.notify.data );
1216         }
1217
1218         /* process each group of messages */
1219
1220         num_groups = notify_msg_ctr_numgroups( &messages );
1221         for ( i=0; i<num_groups; i++ )
1222                 send_notify2_changes( &messages, i );
1223
1224
1225         /* cleanup */
1226
1227         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228
1229         notify_msg_ctr_destroy( &messages );
1230
1231         return;
1232 }
1233
1234 /********************************************************************
1235  Send a message to ourself about new driver being installed
1236  so we can upgrade the information for each printer bound to this
1237  driver
1238  ********************************************************************/
1239
1240 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1241 {
1242         int len = strlen(drivername);
1243
1244         if (!len)
1245                 return False;
1246
1247         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1248                 drivername));
1249
1250         messaging_send_buf(smbd_messaging_context(), procid_self(),
1251                            MSG_PRINTER_DRVUPGRADE,
1252                            (uint8 *)drivername, len+1);
1253
1254         return True;
1255 }
1256
1257 /**********************************************************************
1258  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1259  over all printers, upgrading ones as necessary
1260  **********************************************************************/
1261
1262 void do_drv_upgrade_printer(struct messaging_context *msg,
1263                             void *private_data,
1264                             uint32_t msg_type,
1265                             struct server_id server_id,
1266                             DATA_BLOB *data)
1267 {
1268         fstring drivername;
1269         int snum;
1270         int n_services = lp_numservices();
1271         size_t len;
1272
1273         len = MIN(data->length,sizeof(drivername)-1);
1274         strncpy(drivername, (const char *)data->data, len);
1275
1276         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1277
1278         /* Iterate the printer list */
1279
1280         for (snum=0; snum<n_services; snum++)
1281         {
1282                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1283                 {
1284                         WERROR result;
1285                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1286
1287                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1288                         if (!W_ERROR_IS_OK(result))
1289                                 continue;
1290
1291                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1292                         {
1293                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1294
1295                                 /* all we care about currently is the change_id */
1296
1297                                 result = mod_a_printer(printer, 2);
1298                                 if (!W_ERROR_IS_OK(result)) {
1299                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1300                                                 win_errstr(result)));
1301                                 }
1302                         }
1303
1304                         free_a_printer(&printer, 2);
1305                 }
1306         }
1307
1308         /* all done */
1309 }
1310
1311 /********************************************************************
1312  Update the cache for all printq's with a registered client
1313  connection
1314  ********************************************************************/
1315
1316 void update_monitored_printq_cache( void )
1317 {
1318         Printer_entry *printer = printers_list;
1319         int snum;
1320
1321         /* loop through all printers and update the cache where
1322            client_connected == True */
1323         while ( printer )
1324         {
1325                 if ( (printer->printer_type == SPLHND_PRINTER)
1326                         && printer->notify.client_connected )
1327                 {
1328                         snum = print_queue_snum(printer->sharename);
1329                         print_queue_status( snum, NULL, NULL );
1330                 }
1331
1332                 printer = printer->next;
1333         }
1334
1335         return;
1336 }
1337 /********************************************************************
1338  Send a message to ourself about new driver being installed
1339  so we can upgrade the information for each printer bound to this
1340  driver
1341  ********************************************************************/
1342
1343 static bool srv_spoolss_reset_printerdata(char* drivername)
1344 {
1345         int len = strlen(drivername);
1346
1347         if (!len)
1348                 return False;
1349
1350         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351                 drivername));
1352
1353         messaging_send_buf(smbd_messaging_context(), procid_self(),
1354                            MSG_PRINTERDATA_INIT_RESET,
1355                            (uint8 *)drivername, len+1);
1356
1357         return True;
1358 }
1359
1360 /**********************************************************************
1361  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1362  over all printers, resetting printer data as neessary
1363  **********************************************************************/
1364
1365 void reset_all_printerdata(struct messaging_context *msg,
1366                            void *private_data,
1367                            uint32_t msg_type,
1368                            struct server_id server_id,
1369                            DATA_BLOB *data)
1370 {
1371         fstring drivername;
1372         int snum;
1373         int n_services = lp_numservices();
1374         size_t len;
1375
1376         len = MIN( data->length, sizeof(drivername)-1 );
1377         strncpy( drivername, (const char *)data->data, len );
1378
1379         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1380
1381         /* Iterate the printer list */
1382
1383         for ( snum=0; snum<n_services; snum++ )
1384         {
1385                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1386                 {
1387                         WERROR result;
1388                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1389
1390                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1391                         if ( !W_ERROR_IS_OK(result) )
1392                                 continue;
1393
1394                         /*
1395                          * if the printer is bound to the driver,
1396                          * then reset to the new driver initdata
1397                          */
1398
1399                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1400                         {
1401                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1402
1403                                 if ( !set_driver_init(printer, 2) ) {
1404                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1405                                                 printer->info_2->printername, printer->info_2->drivername));
1406                                 }
1407
1408                                 result = mod_a_printer( printer, 2 );
1409                                 if ( !W_ERROR_IS_OK(result) ) {
1410                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1411                                                 get_dos_error_msg(result)));
1412                                 }
1413                         }
1414
1415                         free_a_printer( &printer, 2 );
1416                 }
1417         }
1418
1419         /* all done */
1420
1421         return;
1422 }
1423
1424 /****************************************************************
1425  _spoolss_OpenPrinter
1426 ****************************************************************/
1427
1428 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1429                             struct spoolss_OpenPrinter *r)
1430 {
1431         struct spoolss_OpenPrinterEx e;
1432         WERROR werr;
1433
1434         ZERO_STRUCT(e.in.userlevel);
1435
1436         e.in.printername        = r->in.printername;
1437         e.in.datatype           = r->in.datatype;
1438         e.in.devmode_ctr        = r->in.devmode_ctr;
1439         e.in.access_mask        = r->in.access_mask;
1440         e.in.level              = 0;
1441
1442         e.out.handle            = r->out.handle;
1443
1444         werr = _spoolss_OpenPrinterEx(p, &e);
1445
1446         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1447                 /* OpenPrinterEx returns this for a bad
1448                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1449                  * instead.
1450                  */
1451                 werr = WERR_INVALID_PRINTER_NAME;
1452         }
1453
1454         return werr;
1455 }
1456
1457 /********************************************************************
1458  FIXME: temporary convert_devicemode_new function
1459  ********************************************************************/
1460
1461 static bool convert_devicemode_new(const char *printername,
1462                                    struct spoolss_DeviceMode *devmode,
1463                                    NT_DEVICEMODE **pp_nt_devmode)
1464 {
1465         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1466
1467         /*
1468          * Ensure nt_devmode is a valid pointer
1469          * as we will be overwriting it.
1470          */
1471
1472         if (nt_devmode == NULL) {
1473                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1474                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1475                         return false;
1476         }
1477
1478         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1479         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1480
1481         nt_devmode->specversion         = devmode->specversion;
1482         nt_devmode->driverversion       = devmode->driverversion;
1483         nt_devmode->size                = devmode->size;
1484         nt_devmode->fields              = devmode->fields;
1485         nt_devmode->orientation         = devmode->orientation;
1486         nt_devmode->papersize           = devmode->papersize;
1487         nt_devmode->paperlength         = devmode->paperlength;
1488         nt_devmode->paperwidth          = devmode->paperwidth;
1489         nt_devmode->scale               = devmode->scale;
1490         nt_devmode->copies              = devmode->copies;
1491         nt_devmode->defaultsource       = devmode->defaultsource;
1492         nt_devmode->printquality        = devmode->printquality;
1493         nt_devmode->color               = devmode->color;
1494         nt_devmode->duplex              = devmode->duplex;
1495         nt_devmode->yresolution         = devmode->yresolution;
1496         nt_devmode->ttoption            = devmode->ttoption;
1497         nt_devmode->collate             = devmode->collate;
1498
1499         nt_devmode->logpixels           = devmode->logpixels;
1500         nt_devmode->bitsperpel          = devmode->bitsperpel;
1501         nt_devmode->pelswidth           = devmode->pelswidth;
1502         nt_devmode->pelsheight          = devmode->pelsheight;
1503         nt_devmode->displayflags        = devmode->displayflags;
1504         nt_devmode->displayfrequency    = devmode->displayfrequency;
1505         nt_devmode->icmmethod           = devmode->icmmethod;
1506         nt_devmode->icmintent           = devmode->icmintent;
1507         nt_devmode->mediatype           = devmode->mediatype;
1508         nt_devmode->dithertype          = devmode->dithertype;
1509         nt_devmode->reserved1           = devmode->reserved1;
1510         nt_devmode->reserved2           = devmode->reserved2;
1511         nt_devmode->panningwidth        = devmode->panningwidth;
1512         nt_devmode->panningheight       = devmode->panningheight;
1513
1514         /*
1515          * Only change private and driverextra if the incoming devmode
1516          * has a new one. JRA.
1517          */
1518
1519         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1520                 SAFE_FREE(nt_devmode->nt_dev_private);
1521                 nt_devmode->driverextra = devmode->__driverextra_length;
1522                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1523                         return false;
1524                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1525         }
1526
1527         *pp_nt_devmode = nt_devmode;
1528
1529         return true;
1530 }
1531
1532 /****************************************************************
1533  _spoolss_OpenPrinterEx
1534 ****************************************************************/
1535
1536 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1537                               struct spoolss_OpenPrinterEx *r)
1538 {
1539         POLICY_HND              *handle = r->out.handle;
1540         char *name = CONST_DISCARD(char *, r->in.printername);
1541         int snum;
1542         Printer_entry *Printer=NULL;
1543
1544         if (!name) {
1545                 return WERR_INVALID_PARAM;
1546         }
1547
1548         /* some sanity check because you can open a printer or a print server */
1549         /* aka: \\server\printer or \\server */
1550
1551         DEBUGADD(3,("checking name: %s\n",name));
1552
1553         if (!open_printer_hnd(p, handle, name, 0)) {
1554                 ZERO_STRUCTP(r->out.handle);
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         Printer=find_printer_index_by_hnd(p, handle);
1559         if ( !Printer ) {
1560                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1561                         "handle we created for printer %s\n", name ));
1562                 close_printer_handle(p,handle);
1563                 ZERO_STRUCTP(r->out.handle);
1564                 return WERR_INVALID_PARAM;
1565         }
1566
1567         /*
1568          * First case: the user is opening the print server:
1569          *
1570          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1571          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1572          *
1573          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1574          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1575          * or if the user is listed in the smb.conf printer admin parameter.
1576          *
1577          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1578          * client view printer folder, but does not show the MSAPW.
1579          *
1580          * Note: this test needs code to check access rights here too. Jeremy
1581          * could you look at this?
1582          *
1583          * Second case: the user is opening a printer:
1584          * NT doesn't let us connect to a printer if the connecting user
1585          * doesn't have print permission.
1586          *
1587          * Third case: user is opening a Port Monitor
1588          * access checks same as opening a handle to the print server.
1589          */
1590
1591         switch (Printer->printer_type )
1592         {
1593         case SPLHND_SERVER:
1594         case SPLHND_PORTMON_TCP:
1595         case SPLHND_PORTMON_LOCAL:
1596                 /* Printserver handles use global struct... */
1597
1598                 snum = -1;
1599
1600                 /* Map standard access rights to object specific access rights */
1601
1602                 se_map_standard(&r->in.access_mask,
1603                                 &printserver_std_mapping);
1604
1605                 /* Deny any object specific bits that don't apply to print
1606                    servers (i.e printer and job specific bits) */
1607
1608                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1609
1610                 if (r->in.access_mask &
1611                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1612                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1613                         close_printer_handle(p, handle);
1614                         ZERO_STRUCTP(r->out.handle);
1615                         return WERR_ACCESS_DENIED;
1616                 }
1617
1618                 /* Allow admin access */
1619
1620                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1621                 {
1622                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1623
1624                         if (!lp_ms_add_printer_wizard()) {
1625                                 close_printer_handle(p, handle);
1626                                 ZERO_STRUCTP(r->out.handle);
1627                                 return WERR_ACCESS_DENIED;
1628                         }
1629
1630                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1631                            and not a printer admin, then fail */
1632
1633                         if ((p->server_info->utok.uid != 0) &&
1634                             !user_has_privileges(p->server_info->ptok,
1635                                                  &se_printop ) &&
1636                             !token_contains_name_in_list(
1637                                     uidtoname(p->server_info->utok.uid),
1638                                     NULL, NULL,
1639                                     p->server_info->ptok,
1640                                     lp_printer_admin(snum))) {
1641                                 close_printer_handle(p, handle);
1642                                 ZERO_STRUCTP(r->out.handle);
1643                                 return WERR_ACCESS_DENIED;
1644                         }
1645
1646                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1647                 }
1648                 else
1649                 {
1650                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1651                 }
1652
1653                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1654                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1655
1656                 /* We fall through to return WERR_OK */
1657                 break;
1658
1659         case SPLHND_PRINTER:
1660                 /* NT doesn't let us connect to a printer if the connecting user
1661                    doesn't have print permission.  */
1662
1663                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1664                         close_printer_handle(p, handle);
1665                         ZERO_STRUCTP(r->out.handle);
1666                         return WERR_BADFID;
1667                 }
1668
1669                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1670
1671                 /* map an empty access mask to the minimum access mask */
1672                 if (r->in.access_mask == 0x0)
1673                         r->in.access_mask = PRINTER_ACCESS_USE;
1674
1675                 /*
1676                  * If we are not serving the printer driver for this printer,
1677                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1678                  * will keep NT clients happy  --jerry
1679                  */
1680
1681                 if (lp_use_client_driver(snum)
1682                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1683                 {
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685                 }
1686
1687                 /* check smb.conf parameters and the the sec_desc */
1688
1689                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1690                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1691                         ZERO_STRUCTP(r->out.handle);
1692                         return WERR_ACCESS_DENIED;
1693                 }
1694
1695                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1696                                    p->server_info->ptok, snum) ||
1697                     !print_access_check(p->server_info, snum,
1698                                         r->in.access_mask)) {
1699                         DEBUG(3, ("access DENIED for printer open\n"));
1700                         close_printer_handle(p, handle);
1701                         ZERO_STRUCTP(r->out.handle);
1702                         return WERR_ACCESS_DENIED;
1703                 }
1704
1705                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1706                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1707                         close_printer_handle(p, handle);
1708                         ZERO_STRUCTP(r->out.handle);
1709                         return WERR_ACCESS_DENIED;
1710                 }
1711
1712                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1713                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1714                 else
1715                         r->in.access_mask = PRINTER_ACCESS_USE;
1716
1717                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1718                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1719
1720                 break;
1721
1722         default:
1723                 /* sanity check to prevent programmer error */
1724                 ZERO_STRUCTP(r->out.handle);
1725                 return WERR_BADFID;
1726         }
1727
1728         Printer->access_granted = r->in.access_mask;
1729
1730         /*
1731          * If the client sent a devmode in the OpenPrinter() call, then
1732          * save it here in case we get a job submission on this handle
1733          */
1734
1735          if ( (Printer->printer_type != SPLHND_SERVER)
1736                 && r->in.devmode_ctr.devmode )
1737          {
1738                 convert_devicemode_new(Printer->sharename,
1739                                        r->in.devmode_ctr.devmode,
1740                                        &Printer->nt_devmode);
1741          }
1742
1743 #if 0   /* JERRY -- I'm doubtful this is really effective */
1744         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1745            optimization in Windows 2000 clients  --jerry */
1746
1747         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1748                 && (RA_WIN2K == get_remote_arch()) )
1749         {
1750                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1751                 sys_usleep( 500000 );
1752         }
1753 #endif
1754
1755         return WERR_OK;
1756 }
1757
1758 /****************************************************************************
1759 ****************************************************************************/
1760
1761 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1762                                               NT_PRINTER_INFO_LEVEL_2 *d)
1763 {
1764         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1765
1766         if (!r || !d) {
1767                 return false;
1768         }
1769
1770         d->attributes           = r->attributes;
1771         d->priority             = r->priority;
1772         d->default_priority     = r->defaultpriority;
1773         d->starttime            = r->starttime;
1774         d->untiltime            = r->untiltime;
1775         d->status               = r->status;
1776         d->cjobs                = r->cjobs;
1777
1778         fstrcpy(d->servername,  r->servername);
1779         fstrcpy(d->printername, r->printername);
1780         fstrcpy(d->sharename,   r->sharename);
1781         fstrcpy(d->portname,    r->portname);
1782         fstrcpy(d->drivername,  r->drivername);
1783         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1784         fstrcpy(d->location,    r->location);
1785         fstrcpy(d->sepfile,     r->sepfile);
1786         fstrcpy(d->printprocessor, r->printprocessor);
1787         fstrcpy(d->datatype,    r->datatype);
1788         fstrcpy(d->parameters,  r->parameters);
1789
1790         return true;
1791 }
1792
1793 /****************************************************************************
1794 ****************************************************************************/
1795
1796 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1797                                      NT_PRINTER_INFO_LEVEL *printer)
1798 {
1799         bool ret;
1800
1801         switch (info_ctr->level) {
1802         case 2:
1803                 /* allocate memory if needed.  Messy because
1804                    convert_printer_info is used to update an existing
1805                    printer or build a new one */
1806
1807                 if (!printer->info_2) {
1808                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1809                         if (!printer->info_2) {
1810                                 DEBUG(0,("convert_printer_info_new: "
1811                                         "talloc() failed!\n"));
1812                                 return false;
1813                         }
1814                 }
1815
1816                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1817                                                         printer->info_2);
1818                 printer->info_2->setuptime = time(NULL);
1819                 return ret;
1820         }
1821
1822         return false;
1823 }
1824
1825 /*******************************************************************
1826 ********************************************************************/
1827
1828 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1829 {
1830         int i;
1831
1832         if (!sarray) {
1833                 *farray = NULL;
1834                 return true;
1835         }
1836
1837         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1838         if (!*farray) {
1839                 return false;
1840         }
1841
1842         for (i=0; sarray[i] != NULL; i++) {
1843                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1844                 if (!*farray) {
1845                         return false;
1846                 }
1847                 fstrcpy((*farray)[i], sarray[i]);
1848         }
1849
1850         fstrcpy((*farray)[i], "");
1851
1852         return true;
1853 }
1854
1855 /*******************************************************************
1856 ********************************************************************/
1857
1858 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1859                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1860 {
1861         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1862
1863         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1864
1865         if (*p == NULL) {
1866                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1867                 if (*p == NULL) {
1868                         return false;
1869                 }
1870                 ZERO_STRUCTP(*p);
1871         }
1872
1873         d = *p;
1874
1875         d->cversion =                   r->version;
1876
1877         fstrcpy(d->name,                r->driver_name);
1878         fstrcpy(d->environment,         r->architecture);
1879         fstrcpy(d->driverpath,          r->driver_path);
1880         fstrcpy(d->datafile,            r->data_file);
1881         fstrcpy(d->configfile,          r->config_file);
1882         fstrcpy(d->helpfile,            r->help_file);
1883         fstrcpy(d->monitorname,         r->monitor_name);
1884         fstrcpy(d->defaultdatatype,     r->default_datatype);
1885
1886         DEBUGADD(8,( "version:         %d\n", d->cversion));
1887         DEBUGADD(8,( "name:            %s\n", d->name));
1888         DEBUGADD(8,( "environment:     %s\n", d->environment));
1889         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1890         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1891         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1892         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1893         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1894         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1895
1896         if (r->dependent_files) {
1897                 if (!string_array_to_fstring_array(r->dependent_files->string,
1898                                                    &d->dependentfiles)) {
1899                         SAFE_FREE(*p);
1900                         return false;
1901                 }
1902         }
1903
1904         return true;
1905 }
1906
1907 /*******************************************************************
1908 ********************************************************************/
1909
1910 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1911                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1912 {
1913         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1914
1915         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1916
1917         if (*p == NULL) {
1918                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1919                 if (*p == NULL) {
1920                         return false;
1921                 }
1922                 ZERO_STRUCTP(*p);
1923         }
1924
1925         d = *p;
1926
1927         d->version =                    r->version;
1928
1929         fstrcpy(d->name,                r->driver_name);
1930         fstrcpy(d->environment,         r->architecture);
1931         fstrcpy(d->driverpath,          r->driver_path);
1932         fstrcpy(d->datafile,            r->data_file);
1933         fstrcpy(d->configfile,          r->config_file);
1934         fstrcpy(d->helpfile,            r->help_file);
1935         fstrcpy(d->monitorname,         r->monitor_name);
1936         fstrcpy(d->defaultdatatype,     r->default_datatype);
1937
1938         DEBUGADD(8,( "version:         %d\n", d->version));
1939         DEBUGADD(8,( "name:            %s\n", d->name));
1940         DEBUGADD(8,( "environment:     %s\n", d->environment));
1941         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1942         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1943         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1944         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1945         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1946         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1947
1948         if (r->dependent_files) {
1949                 if (!string_array_to_fstring_array(r->dependent_files->string,
1950                                                    &d->dependentfiles)) {
1951                         goto error;
1952                 }
1953         }
1954
1955         if (r->previous_names) {
1956                 if (!string_array_to_fstring_array(r->previous_names->string,
1957                                                    &d->previousnames)) {
1958                         goto error;
1959                 }
1960         }
1961
1962         return true;
1963
1964  error:
1965         SAFE_FREE(*p);
1966         return false;
1967 }
1968
1969 /********************************************************************
1970  ********************************************************************/
1971
1972 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1973                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1974                                         uint32_t level)
1975 {
1976         switch (level) {
1977         case 3:
1978                 printer->info_3 = NULL;
1979                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1980                         return false;
1981                 }
1982                 break;
1983         case 6:
1984                 printer->info_6 = NULL;
1985                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1986                         return false;
1987                 }
1988                 break;
1989         default:
1990                 return false;
1991         }
1992
1993         return true;
1994 }
1995
1996 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1997                                 NT_DEVICEMODE **pp_nt_devmode)
1998 {
1999         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
2000
2001         /*
2002          * Ensure nt_devmode is a valid pointer
2003          * as we will be overwriting it.
2004          */
2005
2006         if (nt_devmode == NULL) {
2007                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2008                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2009                         return False;
2010         }
2011
2012         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2013         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2014
2015         nt_devmode->specversion=devmode->specversion;
2016         nt_devmode->driverversion=devmode->driverversion;
2017         nt_devmode->size=devmode->size;
2018         nt_devmode->fields=devmode->fields;
2019         nt_devmode->orientation=devmode->orientation;
2020         nt_devmode->papersize=devmode->papersize;
2021         nt_devmode->paperlength=devmode->paperlength;
2022         nt_devmode->paperwidth=devmode->paperwidth;
2023         nt_devmode->scale=devmode->scale;
2024         nt_devmode->copies=devmode->copies;
2025         nt_devmode->defaultsource=devmode->defaultsource;
2026         nt_devmode->printquality=devmode->printquality;
2027         nt_devmode->color=devmode->color;
2028         nt_devmode->duplex=devmode->duplex;
2029         nt_devmode->yresolution=devmode->yresolution;
2030         nt_devmode->ttoption=devmode->ttoption;
2031         nt_devmode->collate=devmode->collate;
2032
2033         nt_devmode->logpixels=devmode->logpixels;
2034         nt_devmode->bitsperpel=devmode->bitsperpel;
2035         nt_devmode->pelswidth=devmode->pelswidth;
2036         nt_devmode->pelsheight=devmode->pelsheight;
2037         nt_devmode->displayflags=devmode->displayflags;
2038         nt_devmode->displayfrequency=devmode->displayfrequency;
2039         nt_devmode->icmmethod=devmode->icmmethod;
2040         nt_devmode->icmintent=devmode->icmintent;
2041         nt_devmode->mediatype=devmode->mediatype;
2042         nt_devmode->dithertype=devmode->dithertype;
2043         nt_devmode->reserved1=devmode->reserved1;
2044         nt_devmode->reserved2=devmode->reserved2;
2045         nt_devmode->panningwidth=devmode->panningwidth;
2046         nt_devmode->panningheight=devmode->panningheight;
2047
2048         /*
2049          * Only change private and driverextra if the incoming devmode
2050          * has a new one. JRA.
2051          */
2052
2053         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2054                 SAFE_FREE(nt_devmode->nt_dev_private);
2055                 nt_devmode->driverextra=devmode->driverextra;
2056                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2057                         return False;
2058                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2059         }
2060
2061         *pp_nt_devmode = nt_devmode;
2062
2063         return True;
2064 }
2065
2066 /********************************************************************
2067  * _spoolss_enddocprinter_internal.
2068  ********************************************************************/
2069
2070 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2071 {
2072         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2073         int snum;
2074
2075         if (!Printer) {
2076                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2077                 return WERR_BADFID;
2078         }
2079
2080         if (!get_printer_snum(p, handle, &snum, NULL))
2081                 return WERR_BADFID;
2082
2083         Printer->document_started=False;
2084         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2085         /* error codes unhandled so far ... */
2086
2087         return WERR_OK;
2088 }
2089
2090 /****************************************************************
2091  _spoolss_ClosePrinter
2092 ****************************************************************/
2093
2094 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2095                              struct spoolss_ClosePrinter *r)
2096 {
2097         POLICY_HND *handle = r->in.handle;
2098
2099         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2100
2101         if (Printer && Printer->document_started)
2102                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2103
2104         if (!close_printer_handle(p, handle))
2105                 return WERR_BADFID;
2106
2107         /* clear the returned printer handle.  Observed behavior
2108            from Win2k server.  Don't think this really matters.
2109            Previous code just copied the value of the closed
2110            handle.    --jerry */
2111
2112         ZERO_STRUCTP(r->out.handle);
2113
2114         return WERR_OK;
2115 }
2116
2117 /****************************************************************
2118  _spoolss_DeletePrinter
2119 ****************************************************************/
2120
2121 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2122                               struct spoolss_DeletePrinter *r)
2123 {
2124         POLICY_HND *handle = r->in.handle;
2125         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2126         WERROR result;
2127
2128         if (Printer && Printer->document_started)
2129                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2130
2131         result = delete_printer_handle(p, handle);
2132
2133         update_c_setprinter(False);
2134
2135         return result;
2136 }
2137
2138 /*******************************************************************
2139  * static function to lookup the version id corresponding to an
2140  * long architecture string
2141  ******************************************************************/
2142
2143 static int get_version_id (char * arch)
2144 {
2145         int i;
2146         struct table_node archi_table[]= {
2147
2148                 {"Windows 4.0",          "WIN40",       0 },
2149                 {"Windows NT x86",       "W32X86",      2 },
2150                 {"Windows NT R4000",     "W32MIPS",     2 },
2151                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2152                 {"Windows NT PowerPC",   "W32PPC",      2 },
2153                 {"Windows IA64",         "IA64",        3 },
2154                 {"Windows x64",          "x64",         3 },
2155                 {NULL,                   "",            -1 }
2156         };
2157
2158         for (i=0; archi_table[i].long_archi != NULL; i++)
2159         {
2160                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2161                         return (archi_table[i].version);
2162         }
2163
2164         return -1;
2165 }
2166
2167 /****************************************************************
2168  _spoolss_DeletePrinterDriver
2169 ****************************************************************/
2170
2171 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2172                                     struct spoolss_DeletePrinterDriver *r)
2173 {
2174         char *driver;
2175         char *arch;
2176         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2177         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2178         int                             version;
2179         WERROR                          status;
2180         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2181         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2182
2183         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184            and not a printer admin, then fail */
2185
2186         if ( (p->server_info->utok.uid != 0)
2187                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2188                 && !token_contains_name_in_list(
2189                         uidtoname(p->server_info->utok.uid), NULL,
2190                         NULL, p->server_info->ptok,
2191                         lp_printer_admin(-1)) )
2192         {
2193                 return WERR_ACCESS_DENIED;
2194         }
2195
2196         driver = CONST_DISCARD(char *, r->in.driver);
2197         arch   = CONST_DISCARD(char *, r->in.architecture);
2198
2199         /* check that we have a valid driver name first */
2200
2201         if ((version=get_version_id(arch)) == -1)
2202                 return WERR_INVALID_ENVIRONMENT;
2203
2204         ZERO_STRUCT(info);
2205         ZERO_STRUCT(info_win2k);
2206
2207         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2208         {
2209                 /* try for Win2k driver if "Windows NT x86" */
2210
2211                 if ( version == 2 ) {
2212                         version = 3;
2213                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2214                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2215                                 goto done;
2216                         }
2217                 }
2218                 /* otherwise it was a failure */
2219                 else {
2220                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2221                         goto done;
2222                 }
2223
2224         }
2225
2226         if (printer_driver_in_use(info.info_3)) {
2227                 status = WERR_PRINTER_DRIVER_IN_USE;
2228                 goto done;
2229         }
2230
2231         if ( version == 2 )
2232         {
2233                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2234                 {
2235                         /* if we get to here, we now have 2 driver info structures to remove */
2236                         /* remove the Win2k driver first*/
2237
2238                         status_win2k = delete_printer_driver(
2239                                 p, info_win2k.info_3, 3, False );
2240                         free_a_printer_driver( info_win2k, 3 );
2241
2242                         /* this should not have failed---if it did, report to client */
2243                         if ( !W_ERROR_IS_OK(status_win2k) )
2244                         {
2245                                 status = status_win2k;
2246                                 goto done;
2247                         }
2248                 }
2249         }
2250
2251         status = delete_printer_driver(p, info.info_3, version, False);
2252
2253         /* if at least one of the deletes succeeded return OK */
2254
2255         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2256                 status = WERR_OK;
2257
2258 done:
2259         free_a_printer_driver( info, 3 );
2260
2261         return status;
2262 }
2263
2264 /****************************************************************
2265  _spoolss_DeletePrinterDriverEx
2266 ****************************************************************/
2267
2268 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2269                                       struct spoolss_DeletePrinterDriverEx *r)
2270 {
2271         char *driver;
2272         char *arch;
2273         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2274         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2275         int                             version;
2276         uint32_t                        flags = r->in.delete_flags;
2277         bool                            delete_files;
2278         WERROR                          status;
2279         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2280         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2281
2282         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2283            and not a printer admin, then fail */
2284
2285         if ( (p->server_info->utok.uid != 0)
2286                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2287                 && !token_contains_name_in_list(
2288                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2289                         p->server_info->ptok, lp_printer_admin(-1)) )
2290         {
2291                 return WERR_ACCESS_DENIED;
2292         }
2293
2294         driver = CONST_DISCARD(char *, r->in.driver);
2295         arch   = CONST_DISCARD(char *, r->in.architecture);
2296
2297         /* check that we have a valid driver name first */
2298         if ((version=get_version_id(arch)) == -1) {
2299                 /* this is what NT returns */
2300                 return WERR_INVALID_ENVIRONMENT;
2301         }
2302
2303         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2304                 version = r->in.version;
2305
2306         ZERO_STRUCT(info);
2307         ZERO_STRUCT(info_win2k);
2308
2309         status = get_a_printer_driver(&info, 3, driver, arch, version);
2310
2311         if ( !W_ERROR_IS_OK(status) )
2312         {
2313                 /*
2314                  * if the client asked for a specific version,
2315                  * or this is something other than Windows NT x86,
2316                  * then we've failed
2317                  */
2318
2319                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2320                         goto done;
2321
2322                 /* try for Win2k driver if "Windows NT x86" */
2323
2324                 version = 3;
2325                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2326                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2327                         goto done;
2328                 }
2329         }
2330
2331         if ( printer_driver_in_use(info.info_3) ) {
2332                 status = WERR_PRINTER_DRIVER_IN_USE;
2333                 goto done;
2334         }
2335
2336         /*
2337          * we have a couple of cases to consider.
2338          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2339          *     then the delete should fail if **any** files overlap with
2340          *     other drivers
2341          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2342          *     non-overlapping files
2343          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2344          *     is set, the do not delete any files
2345          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2346          */
2347
2348         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2349
2350         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2351
2352         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2353                 /* no idea of the correct error here */
2354                 status = WERR_ACCESS_DENIED;
2355                 goto done;
2356         }
2357
2358
2359         /* also check for W32X86/3 if necessary; maybe we already have? */
2360
2361         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2362                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2363                 {
2364
2365                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2366                                 /* no idea of the correct error here */
2367                                 free_a_printer_driver( info_win2k, 3 );
2368                                 status = WERR_ACCESS_DENIED;
2369                                 goto done;
2370                         }
2371
2372                         /* if we get to here, we now have 2 driver info structures to remove */
2373                         /* remove the Win2k driver first*/
2374
2375                         status_win2k = delete_printer_driver(
2376                                 p, info_win2k.info_3, 3, delete_files);
2377                         free_a_printer_driver( info_win2k, 3 );
2378
2379                         /* this should not have failed---if it did, report to client */
2380
2381                         if ( !W_ERROR_IS_OK(status_win2k) )
2382                                 goto done;
2383                 }
2384         }
2385
2386         status = delete_printer_driver(p, info.info_3, version, delete_files);
2387
2388         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2389                 status = WERR_OK;
2390 done:
2391         free_a_printer_driver( info, 3 );
2392
2393         return status;
2394 }
2395
2396
2397 /****************************************************************************
2398  Internal routine for retreiving printerdata
2399  ***************************************************************************/
2400
2401 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2402                                   const char *key, const char *value, uint32 *type, uint8 **data,
2403                                   uint32 *needed, uint32 in_size  )
2404 {
2405         REGISTRY_VALUE          *val;
2406         uint32                  size;
2407         int                     data_len;
2408
2409         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2410                 return WERR_BADFILE;
2411
2412         *type = regval_type( val );
2413
2414         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2415
2416         size = regval_size( val );
2417
2418         /* copy the min(in_size, len) */
2419
2420         if ( in_size ) {
2421                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2422
2423                 /* special case for 0 length values */
2424                 if ( data_len ) {
2425                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2426                                 return WERR_NOMEM;
2427                 }
2428                 else {
2429                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2430                                 return WERR_NOMEM;
2431                 }
2432         }
2433         else
2434                 *data = NULL;
2435
2436         *needed = size;
2437
2438         DEBUG(5,("get_printer_dataex: copy done\n"));
2439
2440         return WERR_OK;
2441 }
2442
2443 /****************************************************************************
2444  Internal routine for removing printerdata
2445  ***************************************************************************/
2446
2447 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2448 {
2449         return delete_printer_data( printer->info_2, key, value );
2450 }
2451
2452 /****************************************************************************
2453  Internal routine for storing printerdata
2454  ***************************************************************************/
2455
2456 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2457                                   uint32 type, uint8 *data, int real_len  )
2458 {
2459         /* the registry objects enforce uniqueness based on value name */
2460
2461         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2462 }
2463
2464 /********************************************************************
2465  GetPrinterData on a printer server Handle.
2466 ********************************************************************/
2467
2468 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2469 {
2470         int i;
2471
2472         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2473
2474         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2475                 *type = REG_DWORD;
2476                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2477                         return WERR_NOMEM;
2478                 SIVAL(*data, 0, 0x00);
2479                 *needed = 0x4;
2480                 return WERR_OK;
2481         }
2482
2483         if (!StrCaseCmp(value, "BeepEnabled")) {
2484                 *type = REG_DWORD;
2485                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2486                         return WERR_NOMEM;
2487                 SIVAL(*data, 0, 0x00);
2488                 *needed = 0x4;
2489                 return WERR_OK;
2490         }
2491
2492         if (!StrCaseCmp(value, "EventLog")) {
2493                 *type = REG_DWORD;
2494                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2495                         return WERR_NOMEM;
2496                 /* formally was 0x1b */
2497                 SIVAL(*data, 0, 0x0);
2498                 *needed = 0x4;
2499                 return WERR_OK;
2500         }
2501
2502         if (!StrCaseCmp(value, "NetPopup")) {
2503                 *type = REG_DWORD;
2504                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2505                         return WERR_NOMEM;
2506                 SIVAL(*data, 0, 0x00);
2507                 *needed = 0x4;
2508                 return WERR_OK;
2509         }
2510
2511         if (!StrCaseCmp(value, "MajorVersion")) {
2512                 *type = REG_DWORD;
2513                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2514                         return WERR_NOMEM;
2515
2516                 /* Windows NT 4.0 seems to not allow uploading of drivers
2517                    to a server that reports 0x3 as the MajorVersion.
2518                    need to investigate more how Win2k gets around this .
2519                    -- jerry */
2520
2521                 if ( RA_WINNT == get_remote_arch() )
2522                         SIVAL(*data, 0, 2);
2523                 else
2524                         SIVAL(*data, 0, 3);
2525
2526                 *needed = 0x4;
2527                 return WERR_OK;
2528         }
2529
2530         if (!StrCaseCmp(value, "MinorVersion")) {
2531                 *type = REG_DWORD;
2532                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2533                         return WERR_NOMEM;
2534                 SIVAL(*data, 0, 0);
2535                 *needed = 0x4;
2536                 return WERR_OK;
2537         }
2538
2539         /* REG_BINARY
2540          *  uint32 size          = 0x114
2541          *  uint32 major         = 5
2542          *  uint32 minor         = [0|1]
2543          *  uint32 build         = [2195|2600]
2544          *  extra unicode string = e.g. "Service Pack 3"
2545          */
2546         if (!StrCaseCmp(value, "OSVersion")) {
2547                 *type = REG_BINARY;
2548                 *needed = 0x114;
2549
2550                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2551                         return WERR_NOMEM;
2552
2553                 SIVAL(*data, 0, *needed);       /* size */
2554                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2555                 SIVAL(*data, 8, 0);
2556                 SIVAL(*data, 12, 2195);         /* build */
2557
2558                 /* leave extra string empty */
2559
2560                 return WERR_OK;
2561         }
2562
2563
2564         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2565                 const char *string="C:\\PRINTERS";
2566                 *type = REG_SZ;
2567                 *needed = 2*(strlen(string)+1);
2568                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2569                         return WERR_NOMEM;
2570                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2571
2572                 /* it's done by hand ready to go on the wire */
2573                 for (i=0; i<strlen(string); i++) {
2574                         (*data)[2*i]=string[i];
2575                         (*data)[2*i+1]='\0';
2576                 }
2577                 return WERR_OK;
2578         }
2579
2580         if (!StrCaseCmp(value, "Architecture")) {
2581                 const char *string="Windows NT x86";
2582                 *type = REG_SZ;
2583                 *needed = 2*(strlen(string)+1);
2584                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2585                         return WERR_NOMEM;
2586                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2587                 for (i=0; i<strlen(string); i++) {
2588                         (*data)[2*i]=string[i];
2589                         (*data)[2*i+1]='\0';
2590                 }
2591                 return WERR_OK;
2592         }
2593
2594         if (!StrCaseCmp(value, "DsPresent")) {
2595                 *type = REG_DWORD;
2596                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2597                         return WERR_NOMEM;
2598
2599                 /* only show the publish check box if we are a
2600                    memeber of a AD domain */
2601
2602                 if ( lp_security() == SEC_ADS )
2603                         SIVAL(*data, 0, 0x01);
2604                 else
2605                         SIVAL(*data, 0, 0x00);
2606
2607                 *needed = 0x4;
2608                 return WERR_OK;
2609         }
2610
2611         if (!StrCaseCmp(value, "DNSMachineName")) {
2612                 const char *hostname = get_mydnsfullname();
2613
2614                 if (!hostname)
2615                         return WERR_BADFILE;
2616                 *type = REG_SZ;
2617                 *needed = 2*(strlen(hostname)+1);
2618                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2619                         return WERR_NOMEM;
2620                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2621                 for (i=0; i<strlen(hostname); i++) {
2622                         (*data)[2*i]=hostname[i];
2623                         (*data)[2*i+1]='\0';
2624                 }
2625                 return WERR_OK;
2626         }
2627
2628
2629         return WERR_BADFILE;
2630 }
2631
2632 /********************************************************************
2633  * spoolss_getprinterdata
2634  ********************************************************************/
2635
2636 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2637 {
2638         POLICY_HND      *handle = &q_u->handle;
2639         UNISTR2         *valuename = &q_u->valuename;
2640         uint32          in_size = q_u->size;
2641         uint32          *type = &r_u->type;
2642         uint32          *out_size = &r_u->size;
2643         uint8           **data = &r_u->data;
2644         uint32          *needed = &r_u->needed;
2645         WERROR          status;
2646         fstring         value;
2647         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2648         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2649         int             snum = 0;
2650
2651         /*
2652          * Reminder: when it's a string, the length is in BYTES
2653          * even if UNICODE is negociated.
2654          *
2655          * JFM, 4/19/1999
2656          */
2657
2658         *out_size = in_size;
2659
2660         /* in case of problem, return some default values */
2661
2662         *needed = 0;
2663         *type   = 0;
2664
2665         DEBUG(4,("_spoolss_getprinterdata\n"));
2666
2667         if ( !Printer ) {
2668                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2669                 status = WERR_BADFID;
2670                 goto done;
2671         }
2672
2673         unistr2_to_ascii(value, valuename, sizeof(value));
2674
2675         if ( Printer->printer_type == SPLHND_SERVER )
2676                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2677         else
2678         {
2679                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2680                         status = WERR_BADFID;
2681                         goto done;
2682                 }
2683
2684                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2685                 if ( !W_ERROR_IS_OK(status) )
2686                         goto done;
2687
2688                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2689
2690                 if ( strequal(value, "ChangeId") ) {
2691                         *type = REG_DWORD;
2692                         *needed = sizeof(uint32);
2693                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2694                                 status = WERR_NOMEM;
2695                                 goto done;
2696                         }
2697                         SIVAL( *data, 0, printer->info_2->changeid );
2698                         status = WERR_OK;
2699                 }
2700                 else
2701                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2702         }
2703
2704         if (*needed > *out_size)
2705                 status = WERR_MORE_DATA;
2706
2707 done:
2708         if ( !W_ERROR_IS_OK(status) )
2709         {
2710                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2711
2712                 /* reply this param doesn't exist */
2713
2714                 if ( *out_size ) {
2715                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2716                                 if ( printer )
2717                                         free_a_printer( &printer, 2 );
2718                                 return WERR_NOMEM;
2719                         }
2720                 } else {
2721                         *data = NULL;
2722                 }
2723         }
2724
2725         /* cleanup & exit */
2726
2727         if ( printer )
2728                 free_a_printer( &printer, 2 );
2729
2730         return status;
2731 }
2732
2733 /*********************************************************
2734  Connect to the client machine.
2735 **********************************************************/
2736
2737 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2738                         struct sockaddr_storage *client_ss, const char *remote_machine)
2739 {
2740         NTSTATUS ret;
2741         struct cli_state *the_cli;
2742         struct sockaddr_storage rm_addr;
2743
2744         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2745                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2746                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2747                         return False;
2748                 }
2749
2750                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2751                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2752                         return False;
2753                 }
2754         } else {
2755                 char addr[INET6_ADDRSTRLEN];
2756                 rm_addr = *client_ss;
2757                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2758                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2759                         addr));
2760         }
2761
2762         /* setup the connection */
2763
2764         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2765                 &rm_addr, 0, "IPC$", "IPC",
2766                 "", /* username */
2767                 "", /* domain */
2768                 "", /* password */
2769                 0, lp_client_signing(), NULL );
2770
2771         if ( !NT_STATUS_IS_OK( ret ) ) {
2772                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2773                         remote_machine ));
2774                 return False;
2775         }
2776
2777         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2778                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2779                 cli_shutdown(the_cli);
2780                 return False;
2781         }
2782
2783         /*
2784          * Ok - we have an anonymous connection to the IPC$ share.
2785          * Now start the NT Domain stuff :-).
2786          */
2787
2788         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2789         if (!NT_STATUS_IS_OK(ret)) {
2790                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2791                         remote_machine, nt_errstr(ret)));
2792                 cli_shutdown(the_cli);
2793                 return False;
2794         }
2795
2796         return True;
2797 }
2798
2799 /***************************************************************************
2800  Connect to the client.
2801 ****************************************************************************/
2802
2803 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2804                                         uint32 localprinter, uint32 type,
2805                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2806 {
2807         WERROR result;
2808         NTSTATUS status;
2809
2810         /*
2811          * If it's the first connection, contact the client
2812          * and connect to the IPC$ share anonymously
2813          */
2814         if (smb_connections==0) {
2815                 fstring unix_printer;
2816
2817                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2818
2819                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2820                         return False;
2821
2822                 messaging_register(smbd_messaging_context(), NULL,
2823                                    MSG_PRINTER_NOTIFY2,
2824                                    receive_notify2_message_list);
2825                 /* Tell the connections db we're now interested in printer
2826                  * notify messages. */
2827                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2828         }
2829
2830         /*
2831          * Tell the specific printing tdb we want messages for this printer
2832          * by registering our PID.
2833          */
2834
2835         if (!print_notify_register_pid(snum))
2836                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2837
2838         smb_connections++;
2839
2840         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2841                                                  printer,
2842                                                  localprinter,
2843                                                  type,
2844                                                  0,
2845                                                  NULL,
2846                                                  handle,
2847                                                  &result);
2848         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2849                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2850                         win_errstr(result)));
2851
2852         return (W_ERROR_IS_OK(result));
2853 }
2854
2855 /****************************************************************
2856  ****************************************************************/
2857
2858 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2859                                                              const struct spoolss_NotifyOption *r)
2860 {
2861         struct spoolss_NotifyOption *option;
2862         uint32_t i,k;
2863
2864         if (!r) {
2865                 return NULL;
2866         }
2867
2868         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2869         if (!option) {
2870                 return NULL;
2871         }
2872
2873         *option = *r;
2874
2875         if (!option->count) {
2876                 return option;
2877         }
2878
2879         option->types = talloc_zero_array(option,
2880                 struct spoolss_NotifyOptionType, option->count);
2881         if (!option->types) {
2882                 talloc_free(option);
2883                 return NULL;
2884         }
2885
2886         for (i=0; i < option->count; i++) {
2887                 option->types[i] = r->types[i];
2888
2889                 if (option->types[i].count) {
2890                         option->types[i].fields = talloc_zero_array(option,
2891                                 enum spoolss_Field, option->types[i].count);
2892                         if (!option->types[i].fields) {
2893                                 talloc_free(option);
2894                                 return NULL;
2895                         }
2896                         for (k=0; k<option->types[i].count; k++) {
2897                                 option->types[i].fields[k] =
2898                                         r->types[i].fields[k];
2899                         }
2900                 }
2901         }
2902
2903         return option;
2904 }
2905
2906 /****************************************************************
2907  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2908  *
2909  * before replying OK: status=0 a rpc call is made to the workstation
2910  * asking ReplyOpenPrinter
2911  *
2912  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2913  * called from api_spoolss_rffpcnex
2914 ****************************************************************/
2915
2916 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2917                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2918 {
2919         POLICY_HND *handle = r->in.handle;
2920         int snum = -1;
2921         struct spoolss_NotifyOption *option = r->in.notify_options;
2922         struct sockaddr_storage client_ss;
2923
2924         /* store the notify value in the printer struct */
2925
2926         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2927
2928         if (!Printer) {
2929                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2930                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2931                 return WERR_BADFID;
2932         }
2933
2934         Printer->notify.flags           = r->in.flags;
2935         Printer->notify.options         = r->in.options;
2936         Printer->notify.printerlocal    = r->in.printer_local;
2937
2938         TALLOC_FREE(Printer->notify.option);
2939         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2940
2941         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2942
2943         /* Connect to the client machine and send a ReplyOpenPrinter */
2944
2945         if ( Printer->printer_type == SPLHND_SERVER)
2946                 snum = -1;
2947         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2948                         !get_printer_snum(p, handle, &snum, NULL) )
2949                 return WERR_BADFID;
2950
2951         if (!interpret_string_addr(&client_ss, p->client_address,
2952                                    AI_NUMERICHOST)) {
2953                 return WERR_SERVER_UNAVAILABLE;
2954         }
2955
2956         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2957                                         Printer->notify.printerlocal, 1,
2958                                         &Printer->notify.client_hnd, &client_ss))
2959                 return WERR_SERVER_UNAVAILABLE;
2960
2961         Printer->notify.client_connected=True;
2962
2963         return WERR_OK;
2964 }
2965
2966 /*******************************************************************
2967  * fill a notify_info_data with the servername
2968  ********************************************************************/
2969
2970 void spoolss_notify_server_name(int snum,
2971                                        struct spoolss_Notify *data,
2972                                        print_queue_struct *queue,
2973                                        NT_PRINTER_INFO_LEVEL *printer,
2974                                        TALLOC_CTX *mem_ctx)
2975 {
2976         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2977 }
2978
2979 /*******************************************************************
2980  * fill a notify_info_data with the printername (not including the servername).
2981  ********************************************************************/
2982
2983 void spoolss_notify_printer_name(int snum,
2984                                         struct spoolss_Notify *data,
2985                                         print_queue_struct *queue,
2986                                         NT_PRINTER_INFO_LEVEL *printer,
2987                                         TALLOC_CTX *mem_ctx)
2988 {
2989         /* the notify name should not contain the \\server\ part */
2990         char *p = strrchr(printer->info_2->printername, '\\');
2991
2992         if (!p) {
2993                 p = printer->info_2->printername;
2994         } else {
2995                 p++;
2996         }
2997
2998         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with the servicename
3003  ********************************************************************/
3004
3005 void spoolss_notify_share_name(int snum,
3006                                       struct spoolss_Notify *data,
3007                                       print_queue_struct *queue,
3008                                       NT_PRINTER_INFO_LEVEL *printer,
3009                                       TALLOC_CTX *mem_ctx)
3010 {
3011         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3012 }
3013
3014 /*******************************************************************
3015  * fill a notify_info_data with the port name
3016  ********************************************************************/
3017
3018 void spoolss_notify_port_name(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_STRING(data, printer->info_2->portname);
3025 }
3026
3027 /*******************************************************************
3028  * fill a notify_info_data with the printername
3029  * but it doesn't exist, have to see what to do
3030  ********************************************************************/
3031
3032 void spoolss_notify_driver_name(int snum,
3033                                        struct spoolss_Notify *data,
3034                                        print_queue_struct *queue,
3035                                        NT_PRINTER_INFO_LEVEL *printer,
3036                                        TALLOC_CTX *mem_ctx)
3037 {
3038         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3039 }
3040
3041 /*******************************************************************
3042  * fill a notify_info_data with the comment
3043  ********************************************************************/
3044
3045 void spoolss_notify_comment(int snum,
3046                                    struct spoolss_Notify *data,
3047                                    print_queue_struct *queue,
3048                                    NT_PRINTER_INFO_LEVEL *printer,
3049                                    TALLOC_CTX *mem_ctx)
3050 {
3051         char *p;
3052
3053         if (*printer->info_2->comment == '\0') {
3054                 p = lp_comment(snum);
3055         } else {
3056                 p = printer->info_2->comment;
3057         }
3058
3059         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with the comment
3064  * location = "Room 1, floor 2, building 3"
3065  ********************************************************************/
3066
3067 void spoolss_notify_location(int snum,
3068                                     struct spoolss_Notify *data,
3069                                     print_queue_struct *queue,
3070                                     NT_PRINTER_INFO_LEVEL *printer,
3071                                     TALLOC_CTX *mem_ctx)
3072 {
3073         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3074 }
3075
3076 /*******************************************************************
3077  * fill a notify_info_data with the device mode
3078  * jfm:xxxx don't to it for know but that's a real problem !!!
3079  ********************************************************************/
3080
3081 static void spoolss_notify_devmode(int snum,
3082                                    struct spoolss_Notify *data,
3083                                    print_queue_struct *queue,
3084                                    NT_PRINTER_INFO_LEVEL *printer,
3085                                    TALLOC_CTX *mem_ctx)
3086 {
3087         /* for a dummy implementation we have to zero the fields */
3088         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with the separator file name
3093  ********************************************************************/
3094
3095 void spoolss_notify_sepfile(int snum,
3096                                    struct spoolss_Notify *data,
3097                                    print_queue_struct *queue,
3098                                    NT_PRINTER_INFO_LEVEL *printer,
3099                                    TALLOC_CTX *mem_ctx)
3100 {
3101         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with the print processor
3106  * jfm:xxxx return always winprint to indicate we don't do anything to it
3107  ********************************************************************/
3108
3109 void spoolss_notify_print_processor(int snum,
3110                                            struct spoolss_Notify *data,
3111                                            print_queue_struct *queue,
3112                                            NT_PRINTER_INFO_LEVEL *printer,
3113                                            TALLOC_CTX *mem_ctx)
3114 {
3115         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3116 }
3117
3118 /*******************************************************************
3119  * fill a notify_info_data with the print processor options
3120  * jfm:xxxx send an empty string
3121  ********************************************************************/
3122
3123 void spoolss_notify_parameters(int snum,
3124                                       struct spoolss_Notify *data,
3125                                       print_queue_struct *queue,
3126                                       NT_PRINTER_INFO_LEVEL *printer,
3127                                       TALLOC_CTX *mem_ctx)
3128 {
3129         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with the data type
3134  * jfm:xxxx always send RAW as data type
3135  ********************************************************************/
3136
3137 void spoolss_notify_datatype(int snum,
3138                                     struct spoolss_Notify *data,
3139                                     print_queue_struct *queue,
3140                                     NT_PRINTER_INFO_LEVEL *printer,
3141                                     TALLOC_CTX *mem_ctx)
3142 {
3143         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3144 }
3145
3146 /*******************************************************************
3147  * fill a notify_info_data with the security descriptor
3148  * jfm:xxxx send an null pointer to say no security desc
3149  * have to implement security before !
3150  ********************************************************************/
3151
3152 static void spoolss_notify_security_desc(int snum,
3153                                          struct spoolss_Notify *data,
3154                                          print_queue_struct *queue,
3155                                          NT_PRINTER_INFO_LEVEL *printer,
3156                                          TALLOC_CTX *mem_ctx)
3157 {
3158         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3159                                           printer->info_2->secdesc_buf->sd_size,
3160                                           printer->info_2->secdesc_buf->sd);
3161 }
3162
3163 /*******************************************************************
3164  * fill a notify_info_data with the attributes
3165  * jfm:xxxx a samba printer is always shared
3166  ********************************************************************/
3167
3168 void spoolss_notify_attributes(int snum,
3169                                       struct spoolss_Notify *data,
3170                                       print_queue_struct *queue,
3171                                       NT_PRINTER_INFO_LEVEL *printer,
3172                                       TALLOC_CTX *mem_ctx)
3173 {
3174         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3175 }
3176
3177 /*******************************************************************
3178  * fill a notify_info_data with the priority
3179  ********************************************************************/
3180
3181 static void spoolss_notify_priority(int snum,
3182                                     struct spoolss_Notify *data,
3183                                     print_queue_struct *queue,
3184                                     NT_PRINTER_INFO_LEVEL *printer,
3185                                     TALLOC_CTX *mem_ctx)
3186 {
3187         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with the default priority
3192  ********************************************************************/
3193
3194 static void spoolss_notify_default_priority(int snum,
3195                                             struct spoolss_Notify *data,
3196                                             print_queue_struct *queue,
3197                                             NT_PRINTER_INFO_LEVEL *printer,
3198                                             TALLOC_CTX *mem_ctx)
3199 {
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3201 }
3202
3203 /*******************************************************************
3204  * fill a notify_info_data with the start time
3205  ********************************************************************/
3206
3207 static void spoolss_notify_start_time(int snum,
3208                                       struct spoolss_Notify *data,
3209                                       print_queue_struct *queue,
3210                                       NT_PRINTER_INFO_LEVEL *printer,
3211                                       TALLOC_CTX *mem_ctx)
3212 {
3213         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3214 }
3215
3216 /*******************************************************************
3217  * fill a notify_info_data with the until time
3218  ********************************************************************/
3219
3220 static void spoolss_notify_until_time(int snum,
3221                                       struct spoolss_Notify *data,
3222                                       print_queue_struct *queue,
3223                                       NT_PRINTER_INFO_LEVEL *printer,
3224                                       TALLOC_CTX *mem_ctx)
3225 {
3226         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3227 }
3228
3229 /*******************************************************************
3230  * fill a notify_info_data with the status
3231  ********************************************************************/
3232
3233 static void spoolss_notify_status(int snum,
3234                                   struct spoolss_Notify *data,
3235                                   print_queue_struct *queue,
3236                                   NT_PRINTER_INFO_LEVEL *printer,
3237                                   TALLOC_CTX *mem_ctx)
3238 {
3239         print_status_struct status;
3240
3241         print_queue_length(snum, &status);
3242         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3243 }
3244
3245 /*******************************************************************
3246  * fill a notify_info_data with the number of jobs queued
3247  ********************************************************************/
3248
3249 void spoolss_notify_cjobs(int snum,
3250                                  struct spoolss_Notify *data,
3251                                  print_queue_struct *queue,
3252                                  NT_PRINTER_INFO_LEVEL *printer,
3253                                  TALLOC_CTX *mem_ctx)
3254 {
3255         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3256 }
3257
3258 /*******************************************************************
3259  * fill a notify_info_data with the average ppm
3260  ********************************************************************/
3261
3262 static void spoolss_notify_average_ppm(int snum,
3263                                        struct spoolss_Notify *data,
3264                                        print_queue_struct *queue,
3265                                        NT_PRINTER_INFO_LEVEL *printer,
3266                                        TALLOC_CTX *mem_ctx)
3267 {
3268         /* always respond 8 pages per minutes */
3269         /* a little hard ! */
3270         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3271 }
3272
3273 /*******************************************************************
3274  * fill a notify_info_data with username
3275  ********************************************************************/
3276
3277 static void spoolss_notify_username(int snum,
3278                                     struct spoolss_Notify *data,
3279                                     print_queue_struct *queue,
3280                                     NT_PRINTER_INFO_LEVEL *printer,
3281                                     TALLOC_CTX *mem_ctx)
3282 {
3283         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3284 }
3285
3286 /*******************************************************************
3287  * fill a notify_info_data with job status
3288  ********************************************************************/
3289
3290 static void spoolss_notify_job_status(int snum,
3291                                       struct spoolss_Notify *data,
3292                                       print_queue_struct *queue,
3293                                       NT_PRINTER_INFO_LEVEL *printer,
3294                                       TALLOC_CTX *mem_ctx)
3295 {
3296         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3297 }
3298
3299 /*******************************************************************
3300  * fill a notify_info_data with job name
3301  ********************************************************************/
3302
3303 static void spoolss_notify_job_name(int snum,
3304                                     struct spoolss_Notify *data,
3305                                     print_queue_struct *queue,
3306                                     NT_PRINTER_INFO_LEVEL *printer,
3307                                     TALLOC_CTX *mem_ctx)
3308 {
3309         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3310 }
3311
3312 /*******************************************************************
3313  * fill a notify_info_data with job status
3314  ********************************************************************/
3315
3316 static void spoolss_notify_job_status_string(int snum,
3317                                              struct spoolss_Notify *data,
3318                                              print_queue_struct *queue,
3319                                              NT_PRINTER_INFO_LEVEL *printer,
3320                                              TALLOC_CTX *mem_ctx)
3321 {
3322         /*
3323          * Now we're returning job status codes we just return a "" here. JRA.
3324          */
3325
3326         const char *p = "";
3327
3328 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3329         p = "unknown";
3330
3331         switch (queue->status) {
3332         case LPQ_QUEUED:
3333                 p = "Queued";
3334                 break;
3335         case LPQ_PAUSED:
3336                 p = "";    /* NT provides the paused string */
3337                 break;
3338         case LPQ_SPOOLING:
3339                 p = "Spooling";
3340                 break;
3341         case LPQ_PRINTING:
3342                 p = "Printing";
3343                 break;
3344         }
3345 #endif /* NO LONGER NEEDED. */
3346
3347         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3348 }
3349
3350 /*******************************************************************
3351  * fill a notify_info_data with job time
3352  ********************************************************************/
3353
3354 static void spoolss_notify_job_time(int snum,
3355                                     struct spoolss_Notify *data,
3356                                     print_queue_struct *queue,
3357                                     NT_PRINTER_INFO_LEVEL *printer,
3358                                     TALLOC_CTX *mem_ctx)
3359 {
3360         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3361 }
3362
3363 /*******************************************************************
3364  * fill a notify_info_data with job size
3365  ********************************************************************/
3366
3367 static void spoolss_notify_job_size(int snum,
3368                                     struct spoolss_Notify *data,
3369                                     print_queue_struct *queue,
3370                                     NT_PRINTER_INFO_LEVEL *printer,
3371                                     TALLOC_CTX *mem_ctx)
3372 {
3373         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3374 }
3375
3376 /*******************************************************************
3377  * fill a notify_info_data with page info
3378  ********************************************************************/
3379 static void spoolss_notify_total_pages(int snum,
3380                                 struct spoolss_Notify *data,
3381                                 print_queue_struct *queue,
3382                                 NT_PRINTER_INFO_LEVEL *printer,
3383                                 TALLOC_CTX *mem_ctx)
3384 {
3385         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3386 }
3387
3388 /*******************************************************************
3389  * fill a notify_info_data with pages printed info.
3390  ********************************************************************/
3391 static void spoolss_notify_pages_printed(int snum,
3392                                 struct spoolss_Notify *data,
3393                                 print_queue_struct *queue,
3394                                 NT_PRINTER_INFO_LEVEL *printer,
3395                                 TALLOC_CTX *mem_ctx)
3396 {
3397         /* Add code when back-end tracks this */
3398         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3399 }
3400
3401 /*******************************************************************
3402  Fill a notify_info_data with job position.
3403  ********************************************************************/
3404
3405 static void spoolss_notify_job_position(int snum,
3406                                         struct spoolss_Notify *data,
3407                                         print_queue_struct *queue,
3408                                         NT_PRINTER_INFO_LEVEL *printer,
3409                                         TALLOC_CTX *mem_ctx)
3410 {
3411         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3412 }
3413
3414 /*******************************************************************
3415  Fill a notify_info_data with submitted time.
3416  ********************************************************************/
3417
3418 static void spoolss_notify_submitted_time(int snum,
3419                                           struct spoolss_Notify *data,
3420                                           print_queue_struct *queue,
3421                                           NT_PRINTER_INFO_LEVEL *printer,
3422                                           TALLOC_CTX *mem_ctx)
3423 {
3424         data->data.string.string = NULL;
3425         data->data.string.size = 0;
3426
3427         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3428                                &data->data.string.string,
3429                                &data->data.string.size);
3430
3431 }
3432
3433 struct s_notify_info_data_table
3434 {
3435         enum spoolss_NotifyType type;
3436         enum spoolss_Field field;
3437         const char *name;
3438         enum spoolss_NotifyTable variable_type;
3439         void (*fn) (int snum, struct spoolss_Notify *data,
3440                     print_queue_struct *queue,
3441                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3442 };
3443
3444 /* A table describing the various print notification constants and
3445    whether the notification data is a pointer to a variable sized
3446    buffer, a one value uint32 or a two value uint32. */
3447
3448 static const struct s_notify_info_data_table notify_info_data_table[] =
3449 {
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3489 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3490 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3491 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3492 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3493 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3494 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3495 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3496 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3497 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3498 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3499 };
3500
3501 /*******************************************************************
3502  Return the variable_type of info_data structure.
3503 ********************************************************************/
3504
3505 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3506                                                   enum spoolss_Field field)
3507 {
3508         int i=0;
3509
3510         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3511                 if ( (notify_info_data_table[i].type == type) &&
3512                      (notify_info_data_table[i].field == field) ) {
3513                         return notify_info_data_table[i].variable_type;
3514                 }
3515         }
3516
3517         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3518
3519         return 0;
3520 }
3521
3522 /****************************************************************************
3523 ****************************************************************************/
3524
3525 static bool search_notify(enum spoolss_NotifyType type,
3526                           enum spoolss_Field field,
3527                           int *value)
3528 {
3529         int i;
3530
3531         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3532                 if (notify_info_data_table[i].type == type &&
3533                     notify_info_data_table[i].field == field &&
3534                     notify_info_data_table[i].fn != NULL) {
3535                         *value = i;
3536                         return True;
3537                 }
3538         }
3539
3540         return False;
3541 }
3542
3543 /****************************************************************************
3544 ****************************************************************************/
3545
3546 void construct_info_data(struct spoolss_Notify *info_data,
3547                          enum spoolss_NotifyType type,
3548                          enum spoolss_Field field,
3549                          int id)
3550 {
3551         info_data->type                 = type;
3552         info_data->field                = field;
3553         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3554         info_data->job_id               = id;
3555 }
3556
3557 /*******************************************************************
3558  *
3559  * fill a notify_info struct with info asked
3560  *
3561  ********************************************************************/
3562
3563 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3564                                           struct spoolss_NotifyInfo *info,
3565                                           int snum,
3566                                           const struct spoolss_NotifyOptionType *option_type,
3567                                           uint32_t id,
3568                                           TALLOC_CTX *mem_ctx)
3569 {
3570         int field_num,j;
3571         enum spoolss_NotifyType type;
3572         enum spoolss_Field field;
3573
3574         struct spoolss_Notify *current_data;
3575         NT_PRINTER_INFO_LEVEL *printer = NULL;
3576         print_queue_struct *queue=NULL;
3577
3578         type = option_type->type;
3579
3580         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3581                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3582                 option_type->count, lp_servicename(snum)));
3583
3584         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3585                 return False;
3586
3587         for(field_num=0; field_num < option_type->count; field_num++) {
3588                 field = option_type->fields[field_num];
3589
3590                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3591
3592                 if (!search_notify(type, field, &j) )
3593                         continue;
3594
3595                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3596                                                       struct spoolss_Notify,
3597                                                       info->count + 1);
3598                 if (info->notifies == NULL) {
3599                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3600                         free_a_printer(&printer, 2);
3601                         return False;
3602                 }
3603
3604                 current_data = &info->notifies[info->count];
3605
3606                 construct_info_data(current_data, type, field, id);
3607
3608                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3609                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3610
3611                 notify_info_data_table[j].fn(snum, current_data, queue,
3612                                              printer, mem_ctx);
3613
3614                 info->count++;
3615         }
3616
3617         free_a_printer(&printer, 2);
3618         return True;
3619 }
3620
3621 /*******************************************************************
3622  *
3623  * fill a notify_info struct with info asked
3624  *
3625  ********************************************************************/
3626
3627 static bool construct_notify_jobs_info(print_queue_struct *queue,
3628                                        struct spoolss_NotifyInfo *info,
3629                                        NT_PRINTER_INFO_LEVEL *printer,
3630                                        int snum,
3631                                        const struct spoolss_NotifyOptionType *option_type,
3632                                        uint32_t id,
3633                                        TALLOC_CTX *mem_ctx)
3634 {
3635         int field_num,j;
3636         enum spoolss_NotifyType type;
3637         enum spoolss_Field field;
3638         struct spoolss_Notify *current_data;
3639
3640         DEBUG(4,("construct_notify_jobs_info\n"));
3641
3642         type = option_type->type;
3643
3644         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3645                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3646                 option_type->count));
3647
3648         for(field_num=0; field_num<option_type->count; field_num++) {
3649                 field = option_type->fields[field_num];
3650
3651                 if (!search_notify(type, field, &j) )
3652                         continue;
3653
3654                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3655                                                       struct spoolss_Notify,
3656                                                       info->count + 1);
3657                 if (info->notifies == NULL) {
3658                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3659                         return False;
3660                 }
3661
3662                 current_data=&(info->notifies[info->count]);
3663
3664                 construct_info_data(current_data, type, field, id);
3665                 notify_info_data_table[j].fn(snum, current_data, queue,
3666                                              printer, mem_ctx);
3667                 info->count++;
3668         }
3669
3670         return True;
3671 }
3672
3673 /*
3674  * JFM: The enumeration is not that simple, it's even non obvious.
3675  *
3676  * let's take an example: I want to monitor the PRINTER SERVER for
3677  * the printer's name and the number of jobs currently queued.
3678  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3679  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3680  *
3681  * I have 3 printers on the back of my server.
3682  *
3683  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3684  * structures.
3685  *   Number     Data                    Id
3686  *      1       printer 1 name          1
3687  *      2       printer 1 cjob          1
3688  *      3       printer 2 name          2
3689  *      4       printer 2 cjob          2
3690  *      5       printer 3 name          3
3691  *      6       printer 3 name          3
3692  *
3693  * that's the print server case, the printer case is even worse.
3694  */
3695
3696 /*******************************************************************
3697  *
3698  * enumerate all printers on the printserver
3699  * fill a notify_info struct with info asked
3700  *
3701  ********************************************************************/
3702
3703 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3704                                       struct spoolss_NotifyInfo *info,
3705                                       TALLOC_CTX *mem_ctx)
3706 {
3707         int snum;
3708         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3709         int n_services=lp_numservices();
3710         int i;
3711         struct spoolss_NotifyOption *option;
3712         struct spoolss_NotifyOptionType option_type;
3713
3714         DEBUG(4,("printserver_notify_info\n"));
3715
3716         if (!Printer)
3717                 return WERR_BADFID;
3718
3719         option = Printer->notify.option;
3720
3721         info->version   = 2;
3722         info->notifies  = NULL;
3723         info->count     = 0;
3724
3725         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3726            sending a ffpcn() request first */
3727
3728         if ( !option )
3729                 return WERR_BADFID;
3730
3731         for (i=0; i<option->count; i++) {
3732                 option_type = option->types[i];
3733
3734                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3735                         continue;
3736
3737                 for (snum=0; snum<n_services; snum++)
3738                 {
3739                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3740                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3741                 }
3742         }
3743
3744 #if 0
3745         /*
3746          * Debugging information, don't delete.
3747          */
3748
3749         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3750         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3751         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3752
3753         for (i=0; i<info->count; i++) {
3754                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3755                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3756                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3757         }
3758 #endif
3759
3760         return WERR_OK;
3761 }
3762
3763 /*******************************************************************
3764  *
3765  * fill a notify_info struct with info asked
3766  *
3767  ********************************************************************/
3768
3769 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3770                                   TALLOC_CTX *mem_ctx)
3771 {
3772         int snum;
3773         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3774         int i;
3775         uint32 id;
3776         struct spoolss_NotifyOption *option;
3777         struct spoolss_NotifyOptionType option_type;
3778         int count,j;
3779         print_queue_struct *queue=NULL;
3780         print_status_struct status;
3781
3782         DEBUG(4,("printer_notify_info\n"));
3783
3784         if (!Printer)
3785                 return WERR_BADFID;
3786
3787         option = Printer->notify.option;
3788         id = 0x0;
3789
3790         info->version   = 2;
3791         info->notifies  = NULL;
3792         info->count     = 0;
3793
3794         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3795            sending a ffpcn() request first */
3796
3797         if ( !option )
3798                 return WERR_BADFID;
3799
3800         get_printer_snum(p, hnd, &snum, NULL);
3801
3802         for (i=0; i<option->count; i++) {
3803                 option_type = option->types[i];
3804
3805                 switch (option_type.type) {
3806                 case PRINTER_NOTIFY_TYPE:
3807                         if(construct_notify_printer_info(Printer, info, snum,
3808                                                          &option_type, id,
3809                                                          mem_ctx))
3810                                 id--;
3811                         break;
3812
3813                 case JOB_NOTIFY_TYPE: {
3814                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3815
3816                         count = print_queue_status(snum, &queue, &status);
3817
3818                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3819                                 goto done;
3820
3821                         for (j=0; j<count; j++) {
3822                                 construct_notify_jobs_info(&queue[j], info,
3823                                                            printer, snum,
3824                                                            &option_type,
3825                                                            queue[j].job,
3826                                                            mem_ctx);
3827                         }
3828
3829                         free_a_printer(&printer, 2);
3830
3831                 done:
3832                         SAFE_FREE(queue);
3833                         break;
3834                 }
3835                 }
3836         }
3837
3838         /*
3839          * Debugging information, don't delete.
3840          */
3841         /*
3842         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3843         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3844         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3845
3846         for (i=0; i<info->count; i++) {
3847                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3848                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3849                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3850         }
3851         */
3852         return WERR_OK;
3853 }
3854
3855 /****************************************************************
3856  _spoolss_RouterRefreshPrinterChangeNotify
3857 ****************************************************************/
3858
3859 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3860                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3861 {
3862         POLICY_HND *handle = r->in.handle;
3863         struct spoolss_NotifyInfo *info;
3864
3865         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3866         WERROR result = WERR_BADFID;
3867
3868         /* we always have a spoolss_NotifyInfo struct */
3869         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3870         if (!info) {
3871                 result = WERR_NOMEM;
3872                 goto done;
3873         }
3874
3875         *r->out.info = info;
3876
3877         if (!Printer) {
3878                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3879                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3880                 goto done;
3881         }
3882
3883         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3884
3885         /*
3886          *      We are now using the change value, and
3887          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3888          *      I don't have a global notification system, I'm sending back all the
3889          *      informations even when _NOTHING_ has changed.
3890          */
3891
3892         /* We need to keep track of the change value to send back in
3893            RRPCN replies otherwise our updates are ignored. */
3894
3895         Printer->notify.fnpcn = True;
3896
3897         if (Printer->notify.client_connected) {
3898                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3899                         "Saving change value in request [%x]\n",
3900                         r->in.change_low));
3901                 Printer->notify.change = r->in.change_low;
3902         }
3903
3904         /* just ignore the spoolss_NotifyOption */
3905
3906         switch (Printer->printer_type) {
3907                 case SPLHND_SERVER:
3908                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3909                         break;
3910
3911                 case SPLHND_PRINTER:
3912                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3913                         break;
3914         }
3915
3916         Printer->notify.fnpcn = False;
3917
3918 done:
3919         return result;
3920 }
3921
3922 /********************************************************************
3923  * construct_printer_info_0
3924  * fill a printer_info_0 struct
3925  ********************************************************************/
3926
3927 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3928 {
3929         char *chaine = NULL;
3930         int count;
3931         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3932         counter_printer_0 *session_counter;
3933         uint32 global_counter;
3934         struct tm *t;
3935         time_t setuptime;
3936         print_status_struct status;
3937         TALLOC_CTX *ctx = talloc_tos();
3938
3939         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3940                 return False;
3941
3942         init_unistr(&printer->printername, ntprinter->info_2->printername);
3943
3944         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3945         if (!chaine) {
3946                 free_a_printer(&ntprinter,2);
3947                 return false;
3948         }
3949
3950         count = print_queue_length(snum, &status);
3951
3952         /* check if we already have a counter for this printer */
3953         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3954                 if (session_counter->snum == snum)
3955                         break;
3956         }
3957
3958         init_unistr(&printer->servername, chaine);
3959
3960         /* it's the first time, add it to the list */
3961         if (session_counter==NULL) {
3962                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3963                         free_a_printer(&ntprinter, 2);
3964                         return False;
3965                 }
3966                 ZERO_STRUCTP(session_counter);
3967                 session_counter->snum=snum;
3968                 session_counter->counter=0;
3969                 DLIST_ADD(counter_list, session_counter);
3970         }
3971
3972         /* increment it */
3973         session_counter->counter++;
3974
3975         /* JFM:
3976          * the global_counter should be stored in a TDB as it's common to all the clients
3977          * and should be zeroed on samba startup
3978          */
3979         global_counter=session_counter->counter;
3980         printer->cjobs = count;
3981         printer->total_jobs = 0;
3982         printer->total_bytes = 0;
3983
3984         setuptime = (time_t)ntprinter->info_2->setuptime;
3985         t=gmtime(&setuptime);
3986
3987         printer->year = t->tm_year+1900;
3988         printer->month = t->tm_mon+1;
3989         printer->dayofweek = t->tm_wday;
3990         printer->day = t->tm_mday;
3991         printer->hour = t->tm_hour;
3992         printer->minute = t->tm_min;
3993         printer->second = t->tm_sec;
3994         printer->milliseconds = 0;
3995
3996         printer->global_counter = global_counter;
3997         printer->total_pages = 0;
3998
3999         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4000         printer->major_version = 0x0005;        /* NT 5 */
4001         printer->build_version = 0x0893;        /* build 2195 */
4002
4003         printer->unknown7 = 0x1;
4004         printer->unknown8 = 0x0;
4005         printer->unknown9 = 0x0;
4006         printer->session_counter = session_counter->counter;
4007         printer->unknown11 = 0x0;
4008         printer->printer_errors = 0x0;          /* number of print failure */
4009         printer->unknown13 = 0x0;
4010         printer->unknown14 = 0x1;
4011         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4012         printer->unknown16 =  0x0;
4013         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4014         printer->unknown18 =  0x0;
4015         printer->status = nt_printq_status(status.status);
4016         printer->unknown20 =  0x0;
4017         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4018         printer->unknown22 = 0x0;
4019         printer->unknown23 = 0x6;               /* 6  ???*/
4020         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4021         printer->unknown25 = 0;
4022         printer->unknown26 = 0;
4023         printer->unknown27 = 0;
4024         printer->unknown28 = 0;
4025         printer->unknown29 = 0;
4026
4027         free_a_printer(&ntprinter,2);
4028         return (True);
4029 }
4030
4031 /********************************************************************
4032  * construct_printer_info_1
4033  * fill a printer_info_1 struct
4034  ********************************************************************/
4035 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4036 {
4037         char *chaine = NULL;
4038         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4039         TALLOC_CTX *ctx = talloc_tos();
4040
4041         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4042                 return false;
4043
4044         printer->flags=flags;
4045
4046         if (*ntprinter->info_2->comment == '\0') {
4047                 init_unistr(&printer->comment, lp_comment(snum));
4048                 chaine = talloc_asprintf(ctx,
4049                                 "%s,%s,%s", ntprinter->info_2->printername,
4050                                 ntprinter->info_2->drivername, lp_comment(snum));
4051         }
4052         else {
4053                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4054                 chaine = talloc_asprintf(ctx,
4055                                 "%s,%s,%s", ntprinter->info_2->printername,
4056                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4057         }
4058
4059         if (!chaine) {
4060                 free_a_printer(&ntprinter,2);
4061                 return false;
4062         }
4063
4064         init_unistr(&printer->description, chaine);
4065         init_unistr(&printer->name, ntprinter->info_2->printername);
4066
4067         free_a_printer(&ntprinter,2);
4068
4069         return True;
4070 }
4071
4072 /****************************************************************************
4073  Free a DEVMODE struct.
4074 ****************************************************************************/
4075
4076 static void free_dev_mode(DEVICEMODE *dev)
4077 {
4078         if (dev == NULL)
4079                 return;
4080
4081         SAFE_FREE(dev->dev_private);
4082         SAFE_FREE(dev);
4083 }
4084
4085 /****************************************************************************
4086  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
4087  should be valid upon entry
4088 ****************************************************************************/
4089
4090 static WERROR convert_nt_devicemode_new(TALLOC_CTX *mem_ctx,
4091                                         struct spoolss_DeviceMode *r,
4092                                         const NT_DEVICEMODE *ntdevmode)
4093 {
4094         if (!r || !ntdevmode) {
4095                 return WERR_INVALID_PARAM;
4096         }
4097
4098         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
4099         W_ERROR_HAVE_NO_MEMORY(r->devicename);
4100
4101         r->specversion          = ntdevmode->specversion;
4102         r->driverversion        = ntdevmode->driverversion;
4103         r->size                 = ntdevmode->size;
4104         r->__driverextra_length = ntdevmode->driverextra;
4105         r->fields               = ntdevmode->fields;
4106
4107         r->orientation          = ntdevmode->orientation;
4108         r->papersize            = ntdevmode->papersize;
4109         r->paperlength          = ntdevmode->paperlength;
4110         r->paperwidth           = ntdevmode->paperwidth;
4111         r->scale                = ntdevmode->scale;
4112         r->copies               = ntdevmode->copies;
4113         r->defaultsource        = ntdevmode->defaultsource;
4114         r->printquality         = ntdevmode->printquality;
4115         r->color                = ntdevmode->color;
4116         r->duplex               = ntdevmode->duplex;
4117         r->yresolution          = ntdevmode->yresolution;
4118         r->ttoption             = ntdevmode->ttoption;
4119         r->collate              = ntdevmode->collate;
4120
4121         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
4122         W_ERROR_HAVE_NO_MEMORY(r->formname);
4123
4124         /* all 0 below are values that have not been set in the old parsing/copy
4125          * function, maybe they should... - gd */
4126
4127         r->logpixels            = 0;
4128         r->bitsperpel           = 0;
4129         r->pelswidth            = 0;
4130         r->pelsheight           = 0;
4131         r->displayflags         = 0;
4132         r->displayfrequency     = 0;
4133         r->icmmethod            = ntdevmode->icmmethod;
4134         r->icmintent            = ntdevmode->icmintent;
4135         r->mediatype            = ntdevmode->mediatype;
4136         r->dithertype           = ntdevmode->dithertype;
4137         r->reserved1            = 0;
4138         r->reserved2            = 0;
4139         r->panningwidth         = 0;
4140         r->panningheight        = 0;
4141
4142         if (ntdevmode->nt_dev_private != NULL) {
4143                 r->driverextra_data = data_blob_talloc(mem_ctx,
4144                         ntdevmode->nt_dev_private,
4145                         ntdevmode->driverextra);
4146                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
4147         }
4148
4149         return WERR_OK;
4150 }
4151
4152
4153 /****************************************************************************
4154  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4155  should be valid upon entry
4156 ****************************************************************************/
4157
4158 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4159 {
4160         if ( !devmode || !ntdevmode )
4161                 return False;
4162
4163         init_unistr(&devmode->devicename, ntdevmode->devicename);
4164
4165         init_unistr(&devmode->formname, ntdevmode->formname);
4166
4167         devmode->specversion      = ntdevmode->specversion;
4168         devmode->driverversion    = ntdevmode->driverversion;
4169         devmode->size             = ntdevmode->size;
4170         devmode->driverextra      = ntdevmode->driverextra;
4171         devmode->fields           = ntdevmode->fields;
4172
4173         devmode->orientation      = ntdevmode->orientation;
4174         devmode->papersize        = ntdevmode->papersize;
4175         devmode->paperlength      = ntdevmode->paperlength;
4176         devmode->paperwidth       = ntdevmode->paperwidth;
4177         devmode->scale            = ntdevmode->scale;
4178         devmode->copies           = ntdevmode->copies;
4179         devmode->defaultsource    = ntdevmode->defaultsource;
4180         devmode->printquality     = ntdevmode->printquality;
4181         devmode->color            = ntdevmode->color;
4182         devmode->duplex           = ntdevmode->duplex;
4183         devmode->yresolution      = ntdevmode->yresolution;
4184         devmode->ttoption         = ntdevmode->ttoption;
4185         devmode->collate          = ntdevmode->collate;
4186         devmode->icmmethod        = ntdevmode->icmmethod;
4187         devmode->icmintent        = ntdevmode->icmintent;
4188         devmode->mediatype        = ntdevmode->mediatype;
4189         devmode->dithertype       = ntdevmode->dithertype;
4190
4191         if (ntdevmode->nt_dev_private != NULL) {
4192                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4193                         return False;
4194         }
4195
4196         return True;
4197 }
4198
4199 /****************************************************************************
4200  Create a spoolss_DeviceMode struct. Returns talloced memory.
4201 ****************************************************************************/
4202
4203 struct spoolss_DeviceMode *construct_dev_mode_new(TALLOC_CTX *mem_ctx,
4204                                                   const char *servicename)
4205 {
4206         WERROR result;
4207         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4208         struct spoolss_DeviceMode *devmode = NULL;
4209
4210         DEBUG(7,("construct_dev_mode_new\n"));
4211
4212         DEBUGADD(8,("getting printer characteristics\n"));
4213
4214         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4215                 return NULL;
4216
4217         if (!printer->info_2->devmode) {
4218                 DEBUG(5, ("BONG! There was no device mode!\n"));
4219                 goto done;
4220         }
4221
4222         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4223         if (!devmode) {
4224                 DEBUG(2,("construct_dev_mode_new: talloc fail.\n"));
4225                 goto done;
4226         }
4227
4228         DEBUGADD(8,("loading DEVICEMODE\n"));
4229
4230         result = convert_nt_devicemode_new(mem_ctx, devmode, printer->info_2->devmode);
4231         if (!W_ERROR_IS_OK(result)) {
4232                 TALLOC_FREE(devmode);
4233         }
4234
4235 done:
4236         free_a_printer(&printer,2);
4237
4238         return devmode;
4239 }
4240
4241 /****************************************************************************
4242  Create a DEVMODE struct. Returns malloced memory.
4243 ****************************************************************************/
4244
4245 DEVICEMODE *construct_dev_mode(const char *servicename)
4246 {
4247         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4248         DEVICEMODE              *devmode = NULL;
4249
4250         DEBUG(7,("construct_dev_mode\n"));
4251
4252         DEBUGADD(8,("getting printer characteristics\n"));
4253
4254         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4255                 return NULL;
4256
4257         if ( !printer->info_2->devmode ) {
4258                 DEBUG(5, ("BONG! There was no device mode!\n"));
4259                 goto done;
4260         }
4261
4262         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4263                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4264                 goto done;
4265         }
4266
4267         ZERO_STRUCTP(devmode);
4268
4269         DEBUGADD(8,("loading DEVICEMODE\n"));
4270
4271         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4272                 free_dev_mode( devmode );
4273                 devmode = NULL;
4274         }
4275
4276 done:
4277         free_a_printer(&printer,2);
4278
4279         return devmode;
4280 }
4281
4282 /********************************************************************
4283  * construct_printer_info_2
4284  * fill a printer_info_2 struct
4285  ********************************************************************/
4286
4287 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4288 {
4289         int count;
4290         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4291
4292         print_status_struct status;
4293
4294         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4295                 return False;
4296
4297         count = print_queue_length(snum, &status);
4298
4299         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4300         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4301         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4302         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4303         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4304
4305         if (*ntprinter->info_2->comment == '\0')
4306                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4307         else
4308                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4309
4310         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4311         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4312         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4313         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4314         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4315
4316         printer->attributes = ntprinter->info_2->attributes;
4317
4318         printer->priority = ntprinter->info_2->priority;                                /* priority */
4319         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4320         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4321         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4322         printer->status = nt_printq_status(status.status);                      /* status */
4323         printer->cjobs = count;                                                 /* jobs */
4324         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4325
4326         if ( !(printer->devmode = construct_dev_mode(
4327                        lp_const_servicename(snum))) )
4328                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4329
4330         printer->secdesc = NULL;
4331
4332         if ( ntprinter->info_2->secdesc_buf
4333                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4334         {
4335                 /* don't use talloc_steal() here unless you do a deep steal of all
4336                    the SEC_DESC members */
4337
4338                 printer->secdesc = dup_sec_desc( talloc_tos(),
4339                         ntprinter->info_2->secdesc_buf->sd );
4340         }
4341
4342         free_a_printer(&ntprinter, 2);
4343
4344         return True;
4345 }
4346
4347 /********************************************************************
4348  * construct_printer_info_3
4349  * fill a printer_info_3 struct
4350  ********************************************************************/
4351
4352 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4353 {
4354         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4355         PRINTER_INFO_3 *printer = NULL;
4356
4357         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4358                 return False;
4359
4360         *pp_printer = NULL;
4361         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4362                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4363                 free_a_printer(&ntprinter, 2);
4364                 return False;
4365         }
4366
4367         ZERO_STRUCTP(printer);
4368
4369         /* These are the components of the SD we are returning. */
4370
4371         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4372                 /* don't use talloc_steal() here unless you do a deep steal of all
4373                    the SEC_DESC members */
4374
4375                 printer->secdesc = dup_sec_desc( talloc_tos(),
4376                         ntprinter->info_2->secdesc_buf->sd );
4377         }
4378
4379         free_a_printer(&ntprinter, 2);
4380
4381         *pp_printer = printer;
4382         return True;
4383 }
4384
4385 /********************************************************************
4386  * construct_printer_info_4
4387  * fill a printer_info_4 struct
4388  ********************************************************************/
4389
4390 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4391 {
4392         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4393
4394         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4395                 return False;
4396
4397         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4398         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4399         printer->attributes = ntprinter->info_2->attributes;
4400
4401         free_a_printer(&ntprinter, 2);
4402         return True;
4403 }
4404
4405 /********************************************************************
4406  * construct_printer_info_5
4407  * fill a printer_info_5 struct
4408  ********************************************************************/
4409
4410 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4411 {
4412         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4413
4414         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4415                 return False;
4416
4417         init_unistr(&printer->printername, ntprinter->info_2->printername);
4418         init_unistr(&printer->portname, ntprinter->info_2->portname);
4419         printer->attributes = ntprinter->info_2->attributes;
4420
4421         /* these two are not used by NT+ according to MSDN */
4422
4423         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4424         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4425
4426         free_a_printer(&ntprinter, 2);
4427
4428         return True;
4429 }
4430
4431 /********************************************************************
4432  * construct_printer_info_6
4433  * fill a printer_info_6 struct
4434  ********************************************************************/
4435
4436 static bool construct_printer_info_6(Printer_entry *print_hnd,
4437                                      PRINTER_INFO_6 *printer,
4438                                      int snum)
4439 {
4440         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4441         int count;
4442         print_status_struct status;
4443
4444         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4445                                          lp_const_servicename(snum))))
4446                 return False;
4447
4448         count = print_queue_length(snum, &status);
4449
4450         printer->status = nt_printq_status(status.status);
4451
4452         free_a_printer(&ntprinter, 2);
4453
4454         return True;
4455 }
4456
4457 /********************************************************************
4458  * construct_printer_info_7
4459  * fill a printer_info_7 struct
4460  ********************************************************************/
4461
4462 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4463 {
4464         char *guid_str = NULL;
4465         struct GUID guid;
4466
4467         if (is_printer_published(print_hnd, snum, &guid)) {
4468                 if (asprintf(&guid_str, "{%s}",
4469                              GUID_string(talloc_tos(), &guid)) == -1) {
4470                         return false;
4471                 }
4472                 strupper_m(guid_str);
4473                 init_unistr(&printer->guid, guid_str);
4474                 SAFE_FREE(guid_str);
4475                 printer->action = DSPRINT_PUBLISH;
4476         } else {
4477                 init_unistr(&printer->guid, "");
4478                 printer->action = DSPRINT_UNPUBLISH;
4479         }
4480
4481         return True;
4482 }
4483
4484 /********************************************************************
4485  Spoolss_enumprinters.
4486 ********************************************************************/
4487
4488 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4489 {
4490         int snum;
4491         int i;
4492         int n_services=lp_numservices();
4493         PRINTER_INFO_1 *printers=NULL;
4494         PRINTER_INFO_1 current_prt;
4495         WERROR result = WERR_OK;
4496
4497         DEBUG(4,("enum_all_printers_info_1\n"));
4498
4499         for (snum=0; snum<n_services; snum++) {
4500                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4501                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4502
4503                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4504                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4505                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4506                                         *returned=0;
4507                                         return WERR_NOMEM;
4508                                 }
4509                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4510
4511                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4512                                 (*returned)++;
4513                         }
4514                 }
4515         }
4516
4517         /* check the required size. */
4518         for (i=0; i<*returned; i++)
4519                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4520
4521         if (*needed > offered) {
4522                 result = WERR_INSUFFICIENT_BUFFER;
4523                 goto out;
4524         }
4525
4526         if (!rpcbuf_alloc_size(buffer, *needed)) {
4527                 result = WERR_NOMEM;
4528                 goto out;
4529         }
4530
4531         /* fill the buffer with the structures */
4532         for (i=0; i<*returned; i++)
4533                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4534
4535 out:
4536         /* clear memory */
4537
4538         SAFE_FREE(printers);
4539
4540         if ( !W_ERROR_IS_OK(result) )
4541                 *returned = 0;
4542
4543         return result;
4544 }
4545
4546 /********************************************************************
4547  enum_all_printers_info_1_local.
4548 *********************************************************************/
4549
4550 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4551 {
4552         DEBUG(4,("enum_all_printers_info_1_local\n"));
4553
4554         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4555 }
4556
4557 /********************************************************************
4558  enum_all_printers_info_1_name.
4559 *********************************************************************/
4560
4561 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4562 {
4563         char *s = name;
4564
4565         DEBUG(4,("enum_all_printers_info_1_name\n"));
4566
4567         if ((name[0] == '\\') && (name[1] == '\\'))
4568                 s = name + 2;
4569
4570         if (is_myname_or_ipaddr(s)) {
4571                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4572         }
4573         else
4574                 return WERR_INVALID_NAME;
4575 }
4576
4577 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4578 /********************************************************************
4579  enum_all_printers_info_1_remote.
4580 *********************************************************************/
4581
4582 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4583 {
4584         PRINTER_INFO_1 *printer;
4585         fstring printername;
4586         fstring desc;
4587         fstring comment;
4588         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4589         WERROR result = WERR_OK;
4590
4591         /* JFM: currently it's more a place holder than anything else.
4592          * In the spooler world there is a notion of server registration.
4593          * the print servers are registered on the PDC (in the same domain)
4594          *
4595          * We should have a TDB here. The registration is done thru an
4596          * undocumented RPC call.
4597          */
4598
4599         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4600                 return WERR_NOMEM;
4601
4602         *returned=1;
4603
4604         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4605         slprintf(desc, sizeof(desc)-1,"%s", name);
4606         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4607
4608         init_unistr(&printer->description, desc);
4609         init_unistr(&printer->name, printername);
4610         init_unistr(&printer->comment, comment);
4611         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4612
4613         /* check the required size. */
4614         *needed += spoolss_size_printer_info_1(printer);
4615
4616         if (*needed > offered) {
4617                 result = WERR_INSUFFICIENT_BUFFER;
4618                 goto out;
4619         }
4620
4621         if (!rpcbuf_alloc_size(buffer, *needed)) {
4622                 result = WERR_NOMEM;
4623                 goto out;
4624         }
4625
4626         /* fill the buffer with the structures */
4627         smb_io_printer_info_1("", buffer, printer, 0);
4628
4629 out:
4630         /* clear memory */
4631         SAFE_FREE(printer);
4632
4633         if ( !W_ERROR_IS_OK(result) )
4634                 *returned = 0;
4635
4636         return result;
4637 }
4638
4639 #endif
4640
4641 /********************************************************************
4642  enum_all_printers_info_1_network.
4643 *********************************************************************/
4644
4645 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4646 {
4647         char *s = name;
4648
4649         DEBUG(4,("enum_all_printers_info_1_network\n"));
4650
4651         /* If we respond to a enum_printers level 1 on our name with flags
4652            set to PRINTER_ENUM_REMOTE with a list of printers then these
4653            printers incorrectly appear in the APW browse list.
4654            Specifically the printers for the server appear at the workgroup
4655            level where all the other servers in the domain are
4656            listed. Windows responds to this call with a
4657            WERR_CAN_NOT_COMPLETE so we should do the same. */
4658
4659         if (name[0] == '\\' && name[1] == '\\')
4660                  s = name + 2;
4661
4662         if (is_myname_or_ipaddr(s))
4663                  return WERR_CAN_NOT_COMPLETE;
4664
4665         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4666 }
4667
4668 /********************************************************************
4669  * api_spoolss_enumprinters
4670  *
4671  * called from api_spoolss_enumprinters (see this to understand)
4672  ********************************************************************/
4673
4674 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4675 {
4676         int snum;
4677         int i;
4678         int n_services=lp_numservices();
4679         PRINTER_INFO_2 *printers=NULL;
4680         PRINTER_INFO_2 current_prt;
4681         WERROR result = WERR_OK;
4682
4683         *returned = 0;
4684
4685         for (snum=0; snum<n_services; snum++) {
4686                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4687                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4688
4689                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4690                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4691                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4692                                         *returned = 0;
4693                                         return WERR_NOMEM;
4694                                 }
4695
4696                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4697
4698                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4699
4700                                 (*returned)++;
4701                         }
4702                 }
4703         }
4704
4705         /* check the required size. */
4706         for (i=0; i<*returned; i++)
4707                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4708
4709         if (*needed > offered) {
4710                 result = WERR_INSUFFICIENT_BUFFER;
4711                 goto out;
4712         }
4713
4714         if (!rpcbuf_alloc_size(buffer, *needed)) {
4715                 result = WERR_NOMEM;
4716                 goto out;
4717         }
4718
4719         /* fill the buffer with the structures */
4720         for (i=0; i<*returned; i++)
4721                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4722
4723 out:
4724         /* clear memory */
4725
4726         for (i=0; i<*returned; i++)
4727                 free_devmode(printers[i].devmode);
4728
4729         SAFE_FREE(printers);
4730
4731         if ( !W_ERROR_IS_OK(result) )
4732                 *returned = 0;
4733
4734         return result;
4735 }
4736
4737 /********************************************************************
4738  * handle enumeration of printers at level 1
4739  ********************************************************************/
4740
4741 static WERROR enumprinters_level1( uint32 flags, fstring name,
4742                                  RPC_BUFFER *buffer, uint32 offered,
4743                                  uint32 *needed, uint32 *returned)
4744 {
4745         /* Not all the flags are equals */
4746
4747         if (flags & PRINTER_ENUM_LOCAL)
4748                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4749
4750         if (flags & PRINTER_ENUM_NAME)
4751                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4752
4753 #if 0   /* JERRY - disabled for now */
4754         if (flags & PRINTER_ENUM_REMOTE)
4755                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4756 #endif
4757
4758         if (flags & PRINTER_ENUM_NETWORK)
4759                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4760
4761         return WERR_OK; /* NT4sp5 does that */
4762 }
4763
4764 /********************************************************************
4765  * handle enumeration of printers at level 2
4766  ********************************************************************/
4767
4768 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4769                                  RPC_BUFFER *buffer, uint32 offered,
4770                                  uint32 *needed, uint32 *returned)
4771 {
4772         if (flags & PRINTER_ENUM_LOCAL) {
4773                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4774         }
4775
4776         if (flags & PRINTER_ENUM_NAME) {
4777                 if (is_myname_or_ipaddr(canon_servername(servername)))
4778                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4779                 else
4780                         return WERR_INVALID_NAME;
4781         }
4782
4783         if (flags & PRINTER_ENUM_REMOTE)
4784                 return WERR_UNKNOWN_LEVEL;
4785
4786         return WERR_OK;
4787 }
4788
4789 /********************************************************************
4790  * handle enumeration of printers at level 5
4791  ********************************************************************/
4792
4793 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4794                                  RPC_BUFFER *buffer, uint32 offered,
4795                                  uint32 *needed, uint32 *returned)
4796 {
4797 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4798         return WERR_OK;
4799 }
4800
4801 /********************************************************************
4802  * api_spoolss_enumprinters
4803  *
4804  * called from api_spoolss_enumprinters (see this to understand)
4805  ********************************************************************/
4806
4807 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4808 {
4809         uint32 flags = q_u->flags;
4810         UNISTR2 *servername = &q_u->servername;
4811         uint32 level = q_u->level;
4812         RPC_BUFFER *buffer = NULL;
4813         uint32 offered = q_u->offered;
4814         uint32 *needed = &r_u->needed;
4815         uint32 *returned = &r_u->returned;
4816
4817         fstring name;
4818
4819         /* that's an [in out] buffer */
4820
4821         if (!q_u->buffer && (offered!=0)) {
4822                 return WERR_INVALID_PARAM;
4823         }
4824
4825         if (offered > MAX_RPC_DATA_SIZE) {
4826                 return WERR_INVALID_PARAM;
4827         }
4828
4829         rpcbuf_move(q_u->buffer, &r_u->buffer);
4830         buffer = r_u->buffer;
4831
4832         DEBUG(4,("_spoolss_enumprinters\n"));
4833
4834         *needed=0;
4835         *returned=0;
4836
4837         /*
4838          * Level 1:
4839          *          flags==PRINTER_ENUM_NAME
4840          *           if name=="" then enumerates all printers
4841          *           if name!="" then enumerate the printer
4842          *          flags==PRINTER_ENUM_REMOTE
4843          *          name is NULL, enumerate printers
4844          * Level 2: name!="" enumerates printers, name can't be NULL
4845          * Level 3: doesn't exist
4846          * Level 4: does a local registry lookup
4847          * Level 5: same as Level 2
4848          */
4849
4850         unistr2_to_ascii(name, servername, sizeof(name));
4851         strupper_m(name);
4852
4853         switch (level) {
4854         case 1:
4855                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4856         case 2:
4857                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4858         case 5:
4859                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4860         case 3:
4861         case 4:
4862                 break;
4863         }
4864         return WERR_UNKNOWN_LEVEL;
4865 }
4866
4867 /****************************************************************************
4868 ****************************************************************************/
4869
4870 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 {
4872         PRINTER_INFO_0 *printer=NULL;
4873         WERROR result = WERR_OK;
4874
4875         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4876                 return WERR_NOMEM;
4877
4878         construct_printer_info_0(print_hnd, printer, snum);
4879
4880         /* check the required size. */
4881         *needed += spoolss_size_printer_info_0(printer);
4882
4883         if (*needed > offered) {
4884                 result = WERR_INSUFFICIENT_BUFFER;
4885                 goto out;
4886         }
4887
4888         if (!rpcbuf_alloc_size(buffer, *needed)) {
4889                 result = WERR_NOMEM;
4890                 goto out;
4891         }
4892
4893         /* fill the buffer with the structures */
4894         smb_io_printer_info_0("", buffer, printer, 0);
4895
4896 out:
4897         /* clear memory */
4898
4899         SAFE_FREE(printer);
4900
4901         return result;
4902 }
4903
4904 /****************************************************************************
4905 ****************************************************************************/
4906
4907 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4908 {
4909         PRINTER_INFO_1 *printer=NULL;
4910         WERROR result = WERR_OK;
4911
4912         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4913                 return WERR_NOMEM;
4914
4915         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4916
4917         /* check the required size. */
4918         *needed += spoolss_size_printer_info_1(printer);
4919
4920         if (*needed > offered) {
4921                 result = WERR_INSUFFICIENT_BUFFER;
4922                 goto out;
4923         }
4924
4925         if (!rpcbuf_alloc_size(buffer, *needed)) {
4926                 result = WERR_NOMEM;
4927                 goto out;
4928         }
4929
4930         /* fill the buffer with the structures */
4931         smb_io_printer_info_1("", buffer, printer, 0);
4932
4933 out:
4934         /* clear memory */
4935         SAFE_FREE(printer);
4936
4937         return result;
4938 }
4939
4940 /****************************************************************************
4941 ****************************************************************************/
4942
4943 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4944 {
4945         PRINTER_INFO_2 *printer=NULL;
4946         WERROR result = WERR_OK;
4947
4948         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4949                 return WERR_NOMEM;
4950
4951         construct_printer_info_2(print_hnd, printer, snum);
4952
4953         /* check the required size. */
4954         *needed += spoolss_size_printer_info_2(printer);
4955
4956         if (*needed > offered) {
4957                 result = WERR_INSUFFICIENT_BUFFER;
4958                 goto out;
4959         }
4960
4961         if (!rpcbuf_alloc_size(buffer, *needed)) {
4962                 result = WERR_NOMEM;
4963                 goto out;
4964         }
4965
4966         /* fill the buffer with the structures */
4967         if (!smb_io_printer_info_2("", buffer, printer, 0))
4968                 result = WERR_NOMEM;
4969
4970 out:
4971         /* clear memory */
4972         free_printer_info_2(printer);
4973
4974         return result;
4975 }
4976
4977 /****************************************************************************
4978 ****************************************************************************/
4979
4980 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4981 {
4982         PRINTER_INFO_3 *printer=NULL;
4983         WERROR result = WERR_OK;
4984
4985         if (!construct_printer_info_3(print_hnd, &printer, snum))
4986                 return WERR_NOMEM;
4987
4988         /* check the required size. */
4989         *needed += spoolss_size_printer_info_3(printer);
4990
4991         if (*needed > offered) {
4992                 result = WERR_INSUFFICIENT_BUFFER;
4993                 goto out;
4994         }
4995
4996         if (!rpcbuf_alloc_size(buffer, *needed)) {
4997                 result = WERR_NOMEM;
4998                 goto out;
4999         }
5000
5001         /* fill the buffer with the structures */
5002         smb_io_printer_info_3("", buffer, printer, 0);
5003
5004 out:
5005         /* clear memory */
5006         free_printer_info_3(printer);
5007
5008         return result;
5009 }
5010
5011 /****************************************************************************
5012 ****************************************************************************/
5013
5014 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5015 {
5016         PRINTER_INFO_4 *printer=NULL;
5017         WERROR result = WERR_OK;
5018
5019         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
5020                 return WERR_NOMEM;
5021
5022         if (!construct_printer_info_4(print_hnd, printer, snum)) {
5023                 SAFE_FREE(printer);
5024                 return WERR_NOMEM;
5025         }
5026
5027         /* check the required size. */
5028         *needed += spoolss_size_printer_info_4(printer);
5029
5030         if (*needed > offered) {
5031                 result = WERR_INSUFFICIENT_BUFFER;
5032                 goto out;
5033         }
5034
5035         if (!rpcbuf_alloc_size(buffer, *needed)) {
5036                 result = WERR_NOMEM;
5037                 goto out;
5038         }
5039
5040         /* fill the buffer with the structures */
5041         smb_io_printer_info_4("", buffer, printer, 0);
5042
5043 out:
5044         /* clear memory */
5045         free_printer_info_4(printer);
5046
5047         return result;
5048 }
5049
5050 /****************************************************************************
5051 ****************************************************************************/
5052
5053 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5054 {
5055         PRINTER_INFO_5 *printer=NULL;
5056         WERROR result = WERR_OK;
5057
5058         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
5059                 return WERR_NOMEM;
5060
5061         if (!construct_printer_info_5(print_hnd, printer, snum)) {
5062                 free_printer_info_5(printer);
5063                 return WERR_NOMEM;
5064         }
5065
5066         /* check the required size. */
5067         *needed += spoolss_size_printer_info_5(printer);
5068
5069         if (*needed > offered) {
5070                 result = WERR_INSUFFICIENT_BUFFER;
5071                 goto out;
5072         }
5073
5074         if (!rpcbuf_alloc_size(buffer, *needed)) {
5075                 result = WERR_NOMEM;
5076                 goto out;
5077         }
5078
5079         /* fill the buffer with the structures */
5080         smb_io_printer_info_5("", buffer, printer, 0);
5081
5082 out:
5083         /* clear memory */
5084         free_printer_info_5(printer);
5085
5086         return result;
5087 }
5088
5089 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5090                                  int snum,
5091                                  RPC_BUFFER *buffer, uint32 offered,
5092                                  uint32 *needed)
5093 {
5094         PRINTER_INFO_6 *printer;
5095         WERROR result = WERR_OK;
5096
5097         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5098                 return WERR_NOMEM;
5099         }
5100
5101         if (!construct_printer_info_6(print_hnd, printer, snum)) {
5102                 free_printer_info_6(printer);
5103                 return WERR_NOMEM;
5104         }
5105
5106         /* check the required size. */
5107         *needed += spoolss_size_printer_info_6(printer);
5108
5109         if (*needed > offered) {
5110                 result = WERR_INSUFFICIENT_BUFFER;
5111                 goto out;
5112         }
5113
5114         if (!rpcbuf_alloc_size(buffer, *needed)) {
5115                 result = WERR_NOMEM;
5116                 goto out;
5117         }
5118
5119         /* fill the buffer with the structures */
5120         smb_io_printer_info_6("", buffer, printer, 0);
5121
5122 out:
5123         /* clear memory */
5124         free_printer_info_6(printer);
5125
5126         return result;
5127 }
5128
5129 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5130 {
5131         PRINTER_INFO_7 *printer=NULL;
5132         WERROR result = WERR_OK;
5133
5134         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5135                 return WERR_NOMEM;
5136
5137         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5138                 result = WERR_NOMEM;
5139                 goto out;
5140         }
5141
5142         /* check the required size. */
5143         *needed += spoolss_size_printer_info_7(printer);
5144
5145         if (*needed > offered) {
5146                 result = WERR_INSUFFICIENT_BUFFER;
5147                 goto out;
5148         }
5149
5150         if (!rpcbuf_alloc_size(buffer, *needed)) {
5151                 result = WERR_NOMEM;
5152                 goto out;
5153
5154         }
5155
5156         /* fill the buffer with the structures */
5157         smb_io_printer_info_7("", buffer, printer, 0);
5158
5159 out:
5160         /* clear memory */
5161         free_printer_info_7(printer);
5162
5163         return result;
5164 }
5165
5166 /****************************************************************************
5167 ****************************************************************************/
5168
5169 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5170 {
5171         POLICY_HND *handle = &q_u->handle;
5172         uint32 level = q_u->level;
5173         RPC_BUFFER *buffer = NULL;
5174         uint32 offered = q_u->offered;
5175         uint32 *needed = &r_u->needed;
5176         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5177
5178         int snum;
5179
5180         /* that's an [in out] buffer */
5181
5182         if (!q_u->buffer && (offered!=0)) {
5183                 return WERR_INVALID_PARAM;
5184         }
5185
5186         if (offered > MAX_RPC_DATA_SIZE) {
5187                 return WERR_INVALID_PARAM;
5188         }
5189
5190         rpcbuf_move(q_u->buffer, &r_u->buffer);
5191         buffer = r_u->buffer;
5192
5193         *needed=0;
5194
5195         if (!get_printer_snum(p, handle, &snum, NULL))
5196                 return WERR_BADFID;
5197
5198         switch (level) {
5199         case 0:
5200                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5201         case 1:
5202                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5203         case 2:
5204                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5205         case 3:
5206                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5207         case 4:
5208                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5209         case 5:
5210                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5211         case 6:
5212                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5213         case 7:
5214                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5215         }
5216         return WERR_UNKNOWN_LEVEL;
5217 }
5218
5219 /********************************************************************
5220  ********************************************************************/
5221
5222 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5223                                                   fstring *fstring_array,
5224                                                   const char *cservername)
5225 {
5226         int i, num_strings = 0;
5227         const char **array = NULL;
5228
5229         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
5230
5231                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
5232                                                   cservername, fstring_array[i]);
5233                 if (!str) {
5234                         TALLOC_FREE(array);
5235                         return NULL;
5236                 }
5237
5238
5239                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5240                         TALLOC_FREE(array);
5241                         return NULL;
5242                 }
5243         }
5244
5245         if (i > 0) {
5246                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5247                              &array, &num_strings);
5248         }
5249
5250         return array;
5251 }
5252
5253 /********************************************************************
5254  * fill a spoolss_DriverInfo1 struct
5255  ********************************************************************/
5256
5257 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5258                                         struct spoolss_DriverInfo1 *r,
5259                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5260                                         const char *servername,
5261                                         const char *architecture)
5262 {
5263         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5264         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5265
5266         return WERR_OK;
5267 }
5268
5269 /********************************************************************
5270  * fill a spoolss_DriverInfo2 struct
5271  ********************************************************************/
5272
5273 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5274                                         struct spoolss_DriverInfo2 *r,
5275                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5276                                         const char *servername)
5277
5278 {
5279         const char *cservername = canon_servername(servername);
5280
5281         r->version              = driver->info_3->cversion;
5282
5283         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5284         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5285         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5286         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5287
5288         if (strlen(driver->info_3->driverpath)) {
5289                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5290                                 cservername, driver->info_3->driverpath);
5291         } else {
5292                 r->driver_path  = talloc_strdup(mem_ctx, "");
5293         }
5294         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5295
5296         if (strlen(driver->info_3->datafile)) {
5297                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5298                                 cservername, driver->info_3->datafile);
5299         } else {
5300                 r->data_file    = talloc_strdup(mem_ctx, "");
5301         }
5302         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5303
5304         if (strlen(driver->info_3->configfile)) {
5305                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5306                                 cservername, driver->info_3->configfile);
5307         } else {
5308                 r->config_file  = talloc_strdup(mem_ctx, "");
5309         }
5310         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5311
5312         return WERR_OK;
5313 }
5314
5315 /********************************************************************
5316  * fill a spoolss_DriverInfo3 struct
5317  ********************************************************************/
5318
5319 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5320                                         struct spoolss_DriverInfo3 *r,
5321                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5322                                         const char *servername)
5323 {
5324         const char *cservername = canon_servername(servername);
5325
5326         r->version              = driver->info_3->cversion;
5327
5328         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5329         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5330         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5331         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5332
5333         if (strlen(driver->info_3->driverpath)) {
5334                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5335                                 cservername, driver->info_3->driverpath);
5336         } else {
5337                 r->driver_path  = talloc_strdup(mem_ctx, "");
5338         }
5339         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5340
5341         if (strlen(driver->info_3->datafile)) {
5342                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5343                                 cservername, driver->info_3->datafile);
5344         } else {
5345                 r->data_file    = talloc_strdup(mem_ctx, "");
5346         }
5347         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5348
5349         if (strlen(driver->info_3->configfile)) {
5350                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5351                                 cservername, driver->info_3->configfile);
5352         } else {
5353                 r->config_file  = talloc_strdup(mem_ctx, "");
5354         }
5355         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5356
5357         if (strlen(driver->info_3->helpfile)) {
5358                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5359                                 cservername, driver->info_3->helpfile);
5360         } else {
5361                 r->help_file    = talloc_strdup(mem_ctx, "");
5362         }
5363         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5364
5365         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5366         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5367         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5368         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5369
5370         r->dependent_files = string_array_from_driver_info(mem_ctx,
5371                                                            driver->info_3->dependentfiles,
5372                                                            cservername);
5373         return WERR_OK;
5374 }
5375
5376 /********************************************************************
5377  * fill a spoolss_DriverInfo6 struct
5378  ********************************************************************/
5379
5380 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5381                                         struct spoolss_DriverInfo6 *r,
5382                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5383                                         const char *servername)
5384 {
5385         const char *cservername = canon_servername(servername);
5386
5387         r->version              = driver->info_3->cversion;
5388
5389         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5390         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5391         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5392         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5393
5394         if (strlen(driver->info_3->driverpath)) {
5395                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5396                                 cservername, driver->info_3->driverpath);
5397         } else {
5398                 r->driver_path  = talloc_strdup(mem_ctx, "");
5399         }
5400         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5401
5402         if (strlen(driver->info_3->datafile)) {
5403                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5404                                 cservername, driver->info_3->datafile);
5405         } else {
5406                 r->data_file    = talloc_strdup(mem_ctx, "");
5407         }
5408         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5409
5410         if (strlen(driver->info_3->configfile)) {
5411                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5412                                 cservername, driver->info_3->configfile);
5413         } else {
5414                 r->config_file  = talloc_strdup(mem_ctx, "");
5415         }
5416         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5417
5418         if (strlen(driver->info_3->helpfile)) {
5419                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5420                                 cservername, driver->info_3->helpfile);
5421         } else {
5422                 r->help_file    = talloc_strdup(mem_ctx, "");
5423         }
5424         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5425
5426         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5427         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5428         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5429         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5430
5431         r->dependent_files = string_array_from_driver_info(mem_ctx,
5432                                                            driver->info_3->dependentfiles,
5433                                                            cservername);
5434         r->previous_names = string_array_from_driver_info(mem_ctx,
5435                                                           NULL,
5436                                                           cservername);
5437
5438         r->driver_date          = 0;
5439         r->driver_version       = 0;
5440
5441         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5442         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5443         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5444         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5445         r->hardware_id          = talloc_strdup(mem_ctx, "");
5446         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5447         r->provider             = talloc_strdup(mem_ctx, "");
5448         W_ERROR_HAVE_NO_MEMORY(r->provider);
5449
5450         return WERR_OK;
5451 }
5452
5453 /********************************************************************
5454  * fill a DRIVER_INFO_1 struct
5455  ********************************************************************/
5456
5457 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5458 {
5459         init_unistr( &info->name, driver.info_3->name);
5460 }
5461
5462 /********************************************************************
5463  * construct_printer_driver_info_1
5464  ********************************************************************/
5465
5466 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5467                                               struct spoolss_DriverInfo1 *r,
5468                                               int snum,
5469                                               const char *servername,
5470                                               const char *architecture,
5471                                               uint32_t version)
5472 {
5473         NT_PRINTER_INFO_LEVEL *printer = NULL;
5474         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5475         WERROR result;
5476
5477         ZERO_STRUCT(driver);
5478
5479         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5480                 return WERR_INVALID_PRINTER_NAME;
5481
5482         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5483                 free_a_printer(&printer, 2);
5484                 return WERR_UNKNOWN_PRINTER_DRIVER;
5485         }
5486
5487         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5488
5489         free_a_printer(&printer,2);
5490
5491         return result;
5492 }
5493
5494 /********************************************************************
5495  * construct_printer_driver_info_2
5496  * fill a printer_info_2 struct
5497  ********************************************************************/
5498
5499 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5500 {
5501         TALLOC_CTX *ctx = talloc_tos();
5502         char *temp = NULL;
5503         const char *cservername = canon_servername(servername);
5504
5505         info->version=driver.info_3->cversion;
5506
5507         init_unistr( &info->name, driver.info_3->name );
5508         init_unistr( &info->architecture, driver.info_3->environment );
5509
5510         if (strlen(driver.info_3->driverpath)) {
5511                 temp = talloc_asprintf(ctx,
5512                                 "\\\\%s%s",
5513                                 cservername,
5514                                 driver.info_3->driverpath);
5515                 init_unistr( &info->driverpath, temp );
5516         } else {
5517                 init_unistr( &info->driverpath, "" );
5518         }
5519
5520         TALLOC_FREE(temp);
5521         if (strlen(driver.info_3->datafile)) {
5522                 temp = talloc_asprintf(ctx,
5523                                 "\\\\%s%s",
5524                                 cservername,
5525                                 driver.info_3->datafile);
5526                 init_unistr( &info->datafile, temp );
5527         } else
5528                 init_unistr( &info->datafile, "" );
5529
5530         TALLOC_FREE(temp);
5531         if (strlen(driver.info_3->configfile)) {
5532                 temp = talloc_asprintf(ctx,
5533                                 "\\\\%s%s",
5534                                 cservername,
5535                                 driver.info_3->configfile);
5536                 init_unistr( &info->configfile, temp );
5537         } else
5538                 init_unistr( &info->configfile, "" );
5539 }
5540
5541 /********************************************************************
5542  * construct_printer_driver_info_2
5543  * fill a printer_info_2 struct
5544  ********************************************************************/
5545
5546 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5547                                               struct spoolss_DriverInfo2 *r,
5548                                               int snum,
5549                                               const char *servername,
5550                                               const char *architecture,
5551                                               uint32_t version)
5552 {
5553         NT_PRINTER_INFO_LEVEL *printer = NULL;
5554         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5555         WERROR result;
5556
5557         ZERO_STRUCT(printer);
5558         ZERO_STRUCT(driver);
5559
5560         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5561                 return WERR_INVALID_PRINTER_NAME;
5562
5563         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5564                 free_a_printer(&printer, 2);
5565                 return WERR_UNKNOWN_PRINTER_DRIVER;
5566         }
5567
5568         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5569
5570         free_a_printer(&printer,2);
5571
5572         return result;
5573 }
5574
5575 /********************************************************************
5576  * copy a strings array and convert to UNICODE
5577  *
5578  * convert an array of ascii string to a UNICODE string
5579  ********************************************************************/
5580
5581 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5582 {
5583         int i=0;
5584         int j=0;
5585         const char *v;
5586         char *line = NULL;
5587         TALLOC_CTX *ctx = talloc_tos();
5588
5589         DEBUG(6,("init_unistr_array\n"));
5590         *uni_array=NULL;
5591
5592         while (true) {
5593                 if ( !char_array ) {
5594                         v = "";
5595                 } else {
5596                         v = char_array[i];
5597                         if (!v)
5598                                 v = ""; /* hack to handle null lists */
5599                 }
5600
5601                 /* hack to allow this to be used in places other than when generating
5602                    the list of dependent files */
5603
5604                 TALLOC_FREE(line);
5605                 if ( servername ) {
5606                         line = talloc_asprintf(ctx,
5607                                         "\\\\%s%s",
5608                                         canon_servername(servername),
5609                                         v);
5610                 } else {
5611                         line = talloc_strdup(ctx, v);
5612                 }
5613
5614                 if (!line) {
5615                         SAFE_FREE(*uni_array);
5616                         return 0;
5617                 }
5618                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5619
5620                 /* add one extra unit16 for the second terminating NULL */
5621
5622                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5623                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5624                         return 0;
5625                 }
5626
5627                 if ( !strlen(v) )
5628                         break;
5629
5630                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5631                 i++;
5632         }
5633
5634         if (*uni_array) {
5635                 /* special case for ""; we need to add both NULL's here */
5636                 if (!j)
5637                         (*uni_array)[j++]=0x0000;
5638                 (*uni_array)[j]=0x0000;
5639         }
5640
5641         DEBUGADD(6,("last one:done\n"));
5642
5643         /* return size of array in uint16's */
5644
5645         return j+1;
5646 }
5647
5648 /********************************************************************
5649  * construct_printer_info_3
5650  * fill a printer_info_3 struct
5651  ********************************************************************/
5652
5653 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5654 {
5655         char *temp = NULL;
5656         TALLOC_CTX *ctx = talloc_tos();
5657         const char *cservername = canon_servername(servername);
5658
5659         ZERO_STRUCTP(info);
5660
5661         info->version=driver.info_3->cversion;
5662
5663         init_unistr( &info->name, driver.info_3->name );
5664         init_unistr( &info->architecture, driver.info_3->environment );
5665
5666         if (strlen(driver.info_3->driverpath)) {
5667                 temp = talloc_asprintf(ctx,
5668                                 "\\\\%s%s",
5669                                 cservername,
5670                                 driver.info_3->driverpath);
5671                 init_unistr( &info->driverpath, temp );
5672         } else
5673                 init_unistr( &info->driverpath, "" );
5674
5675         TALLOC_FREE(temp);
5676         if (strlen(driver.info_3->datafile)) {
5677                 temp = talloc_asprintf(ctx,
5678                                 "\\\\%s%s",
5679                                 cservername,
5680                                 driver.info_3->datafile);
5681                 init_unistr( &info->datafile, temp );
5682         } else
5683                 init_unistr( &info->datafile, "" );
5684
5685         TALLOC_FREE(temp);
5686         if (strlen(driver.info_3->configfile)) {
5687                 temp = talloc_asprintf(ctx,
5688                                 "\\\\%s%s",
5689                                 cservername,
5690                                 driver.info_3->configfile);
5691                 init_unistr( &info->configfile, temp );
5692         } else
5693                 init_unistr( &info->configfile, "" );
5694
5695         TALLOC_FREE(temp);
5696         if (strlen(driver.info_3->helpfile)) {
5697                 temp = talloc_asprintf(ctx,
5698                                 "\\\\%s%s",
5699                                 cservername,
5700                                 driver.info_3->helpfile);
5701                 init_unistr( &info->helpfile, temp );
5702         } else
5703                 init_unistr( &info->helpfile, "" );
5704
5705         TALLOC_FREE(temp);
5706         init_unistr( &info->monitorname, driver.info_3->monitorname );
5707         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5708
5709         info->dependentfiles=NULL;
5710         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5711 }
5712
5713 /********************************************************************
5714  * construct_printer_info_3
5715  * fill a printer_info_3 struct
5716  ********************************************************************/
5717
5718 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5719                                               struct spoolss_DriverInfo3 *r,
5720                                               int snum,
5721                                               const char *servername,
5722                                               const char *architecture,
5723                                               uint32_t version)
5724 {
5725         NT_PRINTER_INFO_LEVEL *printer = NULL;
5726         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5727         WERROR status;
5728         ZERO_STRUCT(driver);
5729
5730         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5731         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5732         if (!W_ERROR_IS_OK(status))
5733                 return WERR_INVALID_PRINTER_NAME;
5734
5735         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5736         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5737
5738 #if 0   /* JERRY */
5739
5740         /*
5741          * I put this code in during testing.  Helpful when commenting out the
5742          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5743          * as win2k always queries the driver using an infor level of 6.
5744          * I've left it in (but ifdef'd out) because I'll probably
5745          * use it in experimentation again in the future.   --jerry 22/01/2002
5746          */
5747
5748         if (!W_ERROR_IS_OK(status)) {
5749                 /*
5750                  * Is this a W2k client ?
5751                  */
5752                 if (version == 3) {
5753                         /* Yes - try again with a WinNT driver. */
5754                         version = 2;
5755                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5756                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5757                 }
5758 #endif
5759
5760                 if (!W_ERROR_IS_OK(status)) {
5761                         free_a_printer(&printer,2);
5762                         return WERR_UNKNOWN_PRINTER_DRIVER;
5763                 }
5764
5765 #if 0   /* JERRY */
5766         }
5767 #endif
5768
5769
5770         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5771
5772         free_a_printer(&printer,2);
5773
5774         return status;
5775 }
5776
5777 /********************************************************************
5778  * construct_printer_info_6
5779  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5780  ********************************************************************/
5781
5782 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5783 {
5784         char *temp = NULL;
5785         fstring nullstr;
5786         TALLOC_CTX *ctx = talloc_tos();
5787         const char *cservername = canon_servername(servername);
5788
5789         ZERO_STRUCTP(info);
5790         memset(&nullstr, '\0', sizeof(fstring));
5791
5792         info->version=driver.info_3->cversion;
5793
5794         init_unistr( &info->name, driver.info_3->name );
5795         init_unistr( &info->architecture, driver.info_3->environment );
5796
5797         if (strlen(driver.info_3->driverpath)) {
5798                 temp = talloc_asprintf(ctx,
5799                                 "\\\\%s%s",
5800                                 cservername,
5801                                 driver.info_3->driverpath);
5802                 init_unistr( &info->driverpath, temp );
5803         } else
5804                 init_unistr( &info->driverpath, "" );
5805
5806         TALLOC_FREE(temp);
5807         if (strlen(driver.info_3->datafile)) {
5808                 temp = talloc_asprintf(ctx,
5809                                 "\\\\%s%s",
5810                                 cservername,
5811                                 driver.info_3->datafile);
5812                 init_unistr( &info->datafile, temp );
5813         } else
5814                 init_unistr( &info->datafile, "" );
5815
5816         TALLOC_FREE(temp);
5817         if (strlen(driver.info_3->configfile)) {
5818                 temp = talloc_asprintf(ctx,
5819                                 "\\\\%s%s",
5820                                 cservername,
5821                                 driver.info_3->configfile);
5822                 init_unistr( &info->configfile, temp );
5823         } else
5824                 init_unistr( &info->configfile, "" );
5825
5826         TALLOC_FREE(temp);
5827         if (strlen(driver.info_3->helpfile)) {
5828                 temp = talloc_asprintf(ctx,
5829                                 "\\\\%s%s",
5830                                 cservername,
5831                                 driver.info_3->helpfile);
5832                 init_unistr( &info->helpfile, temp );
5833         } else
5834                 init_unistr( &info->helpfile, "" );
5835
5836         TALLOC_FREE(temp);
5837         init_unistr( &info->monitorname, driver.info_3->monitorname );
5838         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5839
5840         info->dependentfiles = NULL;
5841         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5842
5843         info->previousdrivernames=NULL;
5844         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5845
5846         info->driver_date=0;
5847
5848         info->padding=0;
5849         info->driver_version_low=0;
5850         info->driver_version_high=0;
5851
5852         init_unistr( &info->mfgname, "");
5853         init_unistr( &info->oem_url, "");
5854         init_unistr( &info->hardware_id, "");
5855         init_unistr( &info->provider, "");
5856 }
5857
5858 /********************************************************************
5859  * construct_printer_info_6
5860  * fill a printer_info_6 struct
5861  ********************************************************************/
5862
5863 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5864                                               struct spoolss_DriverInfo6 *r,
5865                                               int snum,
5866                                               const char *servername,
5867                                               const char *architecture,
5868                                               uint32_t version)
5869 {
5870         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5871         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5872         WERROR                          status;
5873
5874         ZERO_STRUCT(driver);
5875
5876         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5877
5878         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5879
5880         if (!W_ERROR_IS_OK(status))
5881                 return WERR_INVALID_PRINTER_NAME;
5882
5883         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5884
5885         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5886
5887         if (!W_ERROR_IS_OK(status))
5888         {
5889                 /*
5890                  * Is this a W2k client ?
5891                  */
5892
5893                 if (version < 3) {
5894                         free_a_printer(&printer,2);
5895                         return WERR_UNKNOWN_PRINTER_DRIVER;
5896                 }
5897
5898                 /* Yes - try again with a WinNT driver. */
5899                 version = 2;
5900                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5901                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5902                 if (!W_ERROR_IS_OK(status)) {
5903                         free_a_printer(&printer,2);
5904                         return WERR_UNKNOWN_PRINTER_DRIVER;
5905                 }
5906         }
5907
5908         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5909
5910         free_a_printer(&printer,2);
5911         free_a_printer_driver(driver, 3);
5912
5913         return status;
5914 }
5915
5916 /****************************************************************************
5917 ****************************************************************************/
5918
5919 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5920 {
5921         SAFE_FREE(info->dependentfiles);
5922 }
5923
5924 /****************************************************************************
5925 ****************************************************************************/
5926
5927 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5928 {
5929         SAFE_FREE(info->dependentfiles);
5930 }
5931
5932 /****************************************************************
5933  _spoolss_GetPrinterDriver2
5934 ****************************************************************/
5935
5936 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5937                                   struct spoolss_GetPrinterDriver2 *r)
5938 {
5939         Printer_entry *printer;
5940         WERROR result;
5941
5942         const char *servername;
5943         int snum;
5944
5945         /* that's an [in out] buffer */
5946
5947         if (!r->in.buffer && (r->in.offered != 0)) {
5948                 return WERR_INVALID_PARAM;
5949         }
5950
5951         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5952
5953         if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5954                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5955                 return WERR_INVALID_PRINTER_NAME;
5956         }
5957
5958         *r->out.needed = 0;
5959         *r->out.server_major_version = 0;
5960         *r->out.server_minor_version = 0;
5961
5962         servername = get_server_name(printer);
5963
5964         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5965                 return WERR_BADFID;
5966         }
5967
5968         switch (r->in.level) {
5969         case 1:
5970                 result = construct_printer_driver_info_1(p->mem_ctx,
5971                                                          &r->out.info->info1,
5972                                                          snum,
5973                                                          servername,
5974                                                          r->in.architecture,
5975                                                          r->in.client_major_version);
5976                 break;
5977         case 2:
5978                 result = construct_printer_driver_info_2(p->mem_ctx,
5979                                                          &r->out.info->info2,
5980                                                          snum,
5981                                                          servername,
5982                                                          r->in.architecture,
5983                                                          r->in.client_major_version);
5984                 break;
5985         case 3:
5986                 result = construct_printer_driver_info_3(p->mem_ctx,
5987                                                          &r->out.info->info3,
5988                                                          snum,
5989                                                          servername,
5990                                                          r->in.architecture,
5991                                                          r->in.client_major_version);
5992                 break;
5993         case 6:
5994                 result = construct_printer_driver_info_6(p->mem_ctx,
5995                                                          &r->out.info->info6,
5996                                                          snum,
5997                                                          servername,
5998                                                          r->in.architecture,
5999                                                          r->in.client_major_version);
6000                 break;
6001         default:
6002 #if 0   /* JERRY */
6003         case 101:
6004                 /* apparently this call is the equivalent of
6005                    EnumPrinterDataEx() for the DsDriver key */
6006                 break;
6007 #endif
6008                 result = WERR_UNKNOWN_LEVEL;
6009                 break;
6010         }
6011
6012         if (!W_ERROR_IS_OK(result)) {
6013                 TALLOC_FREE(r->out.info);
6014                 return result;
6015         }
6016
6017         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
6018                                                r->out.info, r->in.level);
6019         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6020
6021         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6022 }
6023
6024
6025 /****************************************************************
6026  _spoolss_StartPagePrinter
6027 ****************************************************************/
6028
6029 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
6030                                  struct spoolss_StartPagePrinter *r)
6031 {
6032         POLICY_HND *handle = r->in.handle;
6033
6034         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6035
6036         if (!Printer) {
6037                 DEBUG(3,("_spoolss_StartPagePrinter: "
6038                         "Error in startpageprinter printer handle\n"));
6039                 return WERR_BADFID;
6040         }
6041
6042         Printer->page_started=True;
6043         return WERR_OK;
6044 }
6045
6046 /****************************************************************
6047  _spoolss_EndPagePrinter
6048 ****************************************************************/
6049
6050 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
6051                                struct spoolss_EndPagePrinter *r)
6052 {
6053         POLICY_HND *handle = r->in.handle;
6054         int snum;
6055
6056         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6057
6058         if (!Printer) {
6059                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
6060                         OUR_HANDLE(handle)));
6061                 return WERR_BADFID;
6062         }
6063
6064         if (!get_printer_snum(p, handle, &snum, NULL))
6065                 return WERR_BADFID;
6066
6067         Printer->page_started=False;
6068         print_job_endpage(snum, Printer->jobid);
6069
6070         return WERR_OK;
6071 }
6072
6073 /****************************************************************
6074  _spoolss_StartDocPrinter
6075 ****************************************************************/
6076
6077 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
6078                                 struct spoolss_StartDocPrinter *r)
6079 {
6080         POLICY_HND *handle = r->in.handle;
6081         uint32_t *jobid = r->out.job_id;
6082         struct spoolss_DocumentInfo1 *info_1;
6083         int snum;
6084         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6085
6086         if (!Printer) {
6087                 DEBUG(2,("_spoolss_StartDocPrinter: "
6088                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6089                 return WERR_BADFID;
6090         }
6091
6092         if (r->in.level != 1) {
6093                 return WERR_UNKNOWN_LEVEL;
6094         }
6095
6096         info_1 = r->in.info.info1;
6097
6098         /*
6099          * a nice thing with NT is it doesn't listen to what you tell it.
6100          * when asked to send _only_ RAW datas, it tries to send datas
6101          * in EMF format.
6102          *
6103          * So I add checks like in NT Server ...
6104          */
6105
6106         if (info_1->datatype) {
6107                 if (strcmp(info_1->datatype, "RAW") != 0) {
6108                         (*jobid)=0;
6109                         return WERR_INVALID_DATATYPE;
6110                 }
6111         }
6112
6113         /* get the share number of the printer */
6114         if (!get_printer_snum(p, handle, &snum, NULL)) {
6115                 return WERR_BADFID;
6116         }
6117
6118         Printer->jobid = print_job_start(p->server_info, snum,
6119                                          info_1->document_name,
6120                                          Printer->nt_devmode);
6121
6122         /* An error occured in print_job_start() so return an appropriate
6123            NT error code. */
6124
6125         if (Printer->jobid == -1) {
6126                 return map_werror_from_unix(errno);
6127         }
6128
6129         Printer->document_started=True;
6130         (*jobid) = Printer->jobid;
6131
6132         return WERR_OK;
6133 }
6134
6135 /****************************************************************
6136  _spoolss_EndDocPrinter
6137 ****************************************************************/
6138
6139 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
6140                               struct spoolss_EndDocPrinter *r)
6141 {
6142         POLICY_HND *handle = r->in.handle;
6143
6144         return _spoolss_enddocprinter_internal(p, handle);
6145 }
6146
6147 /****************************************************************
6148  _spoolss_WritePrinter
6149 ****************************************************************/
6150
6151 WERROR _spoolss_WritePrinter(pipes_struct *p,
6152                              struct spoolss_WritePrinter *r)
6153 {
6154         POLICY_HND *handle = r->in.handle;
6155         uint32 buffer_size = r->in._data_size;
6156         uint8 *buffer = r->in.data.data;
6157         uint32 *buffer_written = &r->in._data_size;
6158         int snum;
6159         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6160
6161         if (!Printer) {
6162                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6163                         OUR_HANDLE(handle)));
6164                 *r->out.num_written = r->in._data_size;
6165                 return WERR_BADFID;
6166         }
6167
6168         if (!get_printer_snum(p, handle, &snum, NULL))
6169                 return WERR_BADFID;
6170
6171         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
6172                                         (SMB_OFF_T)-1, (size_t)buffer_size);
6173         if (*buffer_written == (uint32)-1) {
6174                 *r->out.num_written = 0;
6175                 if (errno == ENOSPC)
6176                         return WERR_NO_SPOOL_SPACE;
6177                 else
6178                         return WERR_ACCESS_DENIED;
6179         }
6180
6181         *r->out.num_written = r->in._data_size;
6182
6183         return WERR_OK;
6184 }
6185
6186 /********************************************************************
6187  * api_spoolss_getprinter
6188  * called from the spoolss dispatcher
6189  *
6190  ********************************************************************/
6191
6192 static WERROR control_printer(POLICY_HND *handle, uint32 command,
6193                               pipes_struct *p)
6194 {
6195         int snum;
6196         WERROR errcode = WERR_BADFUNC;
6197         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6198
6199         if (!Printer) {
6200                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6201                 return WERR_BADFID;
6202         }
6203
6204         if (!get_printer_snum(p, handle, &snum, NULL))
6205                 return WERR_BADFID;
6206
6207         switch (command) {
6208         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6209                 if (print_queue_pause(p->server_info, snum, &errcode)) {
6210                         errcode = WERR_OK;
6211                 }
6212                 break;
6213         case SPOOLSS_PRINTER_CONTROL_RESUME:
6214         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6215                 if (print_queue_resume(p->server_info, snum, &errcode)) {
6216                         errcode = WERR_OK;
6217                 }
6218                 break;
6219         case SPOOLSS_PRINTER_CONTROL_PURGE:
6220                 if (print_queue_purge(p->server_info, snum, &errcode)) {
6221                         errcode = WERR_OK;
6222                 }
6223                 break;
6224         default:
6225                 return WERR_UNKNOWN_LEVEL;
6226         }
6227
6228         return errcode;
6229 }
6230
6231
6232 /****************************************************************
6233  _spoolss_AbortPrinter
6234  * From MSDN: "Deletes printer's spool file if printer is configured
6235  * for spooling"
6236 ****************************************************************/
6237
6238 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6239                              struct spoolss_AbortPrinter *r)
6240 {
6241         POLICY_HND      *handle = r->in.handle;
6242         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6243         int             snum;
6244         WERROR          errcode = WERR_OK;
6245
6246         if (!Printer) {
6247                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6248                         OUR_HANDLE(handle)));
6249                 return WERR_BADFID;
6250         }
6251
6252         if (!get_printer_snum(p, handle, &snum, NULL))
6253                 return WERR_BADFID;
6254
6255         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6256
6257         return errcode;
6258 }
6259
6260 /********************************************************************
6261  * called by spoolss_api_setprinter
6262  * when updating a printer description
6263  ********************************************************************/
6264
6265 static WERROR update_printer_sec(POLICY_HND *handle,
6266                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6267 {
6268         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6269         WERROR result;
6270         int snum;
6271
6272         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6273
6274         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6275                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6276                          OUR_HANDLE(handle)));
6277
6278                 result = WERR_BADFID;
6279                 goto done;
6280         }
6281
6282         if (!secdesc_ctr) {
6283                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6284                 result = WERR_INVALID_PARAM;
6285                 goto done;
6286         }
6287
6288         /* Check the user has permissions to change the security
6289            descriptor.  By experimentation with two NT machines, the user
6290            requires Full Access to the printer to change security
6291            information. */
6292
6293         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6294                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6295                 result = WERR_ACCESS_DENIED;
6296                 goto done;
6297         }
6298
6299         /* NT seems to like setting the security descriptor even though
6300            nothing may have actually changed. */
6301
6302         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6303                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6304                 result = WERR_BADFID;
6305                 goto done;
6306         }
6307
6308         if (DEBUGLEVEL >= 10) {
6309                 SEC_ACL *the_acl;
6310                 int i;
6311
6312                 the_acl = old_secdesc_ctr->sd->dacl;
6313                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6314                            PRINTERNAME(snum), the_acl->num_aces));
6315
6316                 for (i = 0; i < the_acl->num_aces; i++) {
6317                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6318                                            &the_acl->aces[i].trustee),
6319                                   the_acl->aces[i].access_mask));
6320                 }
6321
6322                 the_acl = secdesc_ctr->sd->dacl;
6323
6324                 if (the_acl) {
6325                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6326                                    PRINTERNAME(snum), the_acl->num_aces));
6327
6328                         for (i = 0; i < the_acl->num_aces; i++) {
6329                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6330                                                    &the_acl->aces[i].trustee),
6331                                            the_acl->aces[i].access_mask));
6332                         }
6333                 } else {
6334                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6335                 }
6336         }
6337
6338         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6339         if (!new_secdesc_ctr) {
6340                 result = WERR_NOMEM;
6341                 goto done;
6342         }
6343
6344         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6345                 result = WERR_OK;
6346                 goto done;
6347         }
6348
6349         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6350
6351  done:
6352
6353         return result;
6354 }
6355
6356 /********************************************************************
6357  Canonicalize printer info from a client
6358
6359  ATTN: It does not matter what we set the servername to hear
6360  since we do the necessary work in get_a_printer() to set it to
6361  the correct value based on what the client sent in the
6362  _spoolss_open_printer_ex().
6363  ********************************************************************/
6364
6365 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6366 {
6367         fstring printername;
6368         const char *p;
6369
6370         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6371                 "portname=%s drivername=%s comment=%s location=%s\n",
6372                 info->servername, info->printername, info->sharename,
6373                 info->portname, info->drivername, info->comment, info->location));
6374
6375         /* we force some elements to "correct" values */
6376         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6377         fstrcpy(info->sharename, lp_servicename(snum));
6378
6379         /* check to see if we allow printername != sharename */
6380
6381         if ( lp_force_printername(snum) ) {
6382                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6383                         global_myname(), info->sharename );
6384         } else {
6385
6386                 /* make sure printername is in \\server\printername format */
6387
6388                 fstrcpy( printername, info->printername );
6389                 p = printername;
6390                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6391                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6392                                 p++;
6393                 }
6394
6395                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6396                          global_myname(), p );
6397         }
6398
6399         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6400         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6401
6402
6403
6404         return True;
6405 }
6406
6407 /****************************************************************************
6408 ****************************************************************************/
6409
6410 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6411 {
6412         char *cmd = lp_addport_cmd();
6413         char *command = NULL;
6414         int ret;
6415         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6416         bool is_print_op = False;
6417
6418         if ( !*cmd ) {
6419                 return WERR_ACCESS_DENIED;
6420         }
6421
6422         command = talloc_asprintf(ctx,
6423                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6424         if (!command) {
6425                 return WERR_NOMEM;
6426         }
6427
6428         if ( token )
6429                 is_print_op = user_has_privileges( token, &se_printop );
6430
6431         DEBUG(10,("Running [%s]\n", command));
6432
6433         /********* BEGIN SePrintOperatorPrivilege **********/
6434
6435         if ( is_print_op )
6436                 become_root();
6437
6438         ret = smbrun(command, NULL);
6439
6440         if ( is_print_op )
6441                 unbecome_root();
6442
6443         /********* END SePrintOperatorPrivilege **********/
6444
6445         DEBUGADD(10,("returned [%d]\n", ret));
6446
6447         TALLOC_FREE(command);
6448
6449         if ( ret != 0 ) {
6450                 return WERR_ACCESS_DENIED;
6451         }
6452
6453         return WERR_OK;
6454 }
6455
6456 /****************************************************************************
6457 ****************************************************************************/
6458
6459 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6460 {
6461         char *cmd = lp_addprinter_cmd();
6462         char **qlines;
6463         char *command = NULL;
6464         int numlines;
6465         int ret;
6466         int fd;
6467         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6468         bool is_print_op = False;
6469         char *remote_machine = talloc_strdup(ctx, "%m");
6470
6471         if (!remote_machine) {
6472                 return false;
6473         }
6474         remote_machine = talloc_sub_basic(ctx,
6475                                 current_user_info.smb_name,
6476                                 current_user_info.domain,
6477                                 remote_machine);
6478         if (!remote_machine) {
6479                 return false;
6480         }
6481
6482         command = talloc_asprintf(ctx,
6483                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6484                         cmd, printer->info_2->printername, printer->info_2->sharename,
6485                         printer->info_2->portname, printer->info_2->drivername,
6486                         printer->info_2->location, printer->info_2->comment, remote_machine);
6487         if (!command) {
6488                 return false;
6489         }
6490
6491         if ( token )
6492                 is_print_op = user_has_privileges( token, &se_printop );
6493
6494         DEBUG(10,("Running [%s]\n", command));
6495
6496         /********* BEGIN SePrintOperatorPrivilege **********/
6497
6498         if ( is_print_op )
6499                 become_root();
6500
6501         if ( (ret = smbrun(command, &fd)) == 0 ) {
6502                 /* Tell everyone we updated smb.conf. */
6503                 message_send_all(smbd_messaging_context(),
6504                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6505         }
6506
6507         if ( is_print_op )
6508                 unbecome_root();
6509
6510         /********* END SePrintOperatorPrivilege **********/
6511
6512         DEBUGADD(10,("returned [%d]\n", ret));
6513
6514         TALLOC_FREE(command);
6515         TALLOC_FREE(remote_machine);
6516
6517         if ( ret != 0 ) {
6518                 if (fd != -1)
6519                         close(fd);
6520                 return False;
6521         }
6522
6523         /* reload our services immediately */
6524         reload_services( False );
6525
6526         numlines = 0;
6527         /* Get lines and convert them back to dos-codepage */
6528         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6529         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6530         close(fd);
6531
6532         /* Set the portname to what the script says the portname should be. */
6533         /* but don't require anything to be return from the script exit a good error code */
6534
6535         if (numlines) {
6536                 /* Set the portname to what the script says the portname should be. */
6537                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6538                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6539         }
6540
6541         TALLOC_FREE(qlines);
6542         return True;
6543 }
6544
6545
6546 /********************************************************************
6547  * Called by spoolss_api_setprinter
6548  * when updating a printer description.
6549  ********************************************************************/
6550
6551 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6552                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6553                              struct spoolss_DeviceMode *devmode)
6554 {
6555         int snum;
6556         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6557         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6558         WERROR result;
6559         UNISTR2 buffer;
6560         fstring asc_buffer;
6561
6562         DEBUG(8,("update_printer\n"));
6563
6564         result = WERR_OK;
6565
6566         if (!Printer) {
6567                 result = WERR_BADFID;
6568                 goto done;
6569         }
6570
6571         if (!get_printer_snum(p, handle, &snum, NULL)) {
6572                 result = WERR_BADFID;
6573                 goto done;
6574         }
6575
6576         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6577             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6578                 result = WERR_BADFID;
6579                 goto done;
6580         }
6581
6582         DEBUGADD(8,("Converting info_2 struct\n"));
6583
6584         /*
6585          * convert_printer_info converts the incoming
6586          * info from the client and overwrites the info
6587          * just read from the tdb in the pointer 'printer'.
6588          */
6589
6590         if (!convert_printer_info_new(info_ctr, printer)) {
6591                 result =  WERR_NOMEM;
6592                 goto done;
6593         }
6594
6595         if (devmode) {
6596                 /* we have a valid devmode
6597                    convert it and link it*/
6598
6599                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6600                 if (!convert_devicemode_new(printer->info_2->printername,
6601                                             devmode,
6602                                             &printer->info_2->devmode)) {
6603                         result =  WERR_NOMEM;
6604                         goto done;
6605                 }
6606         }
6607
6608         /* Do sanity check on the requested changes for Samba */
6609
6610         if (!check_printer_ok(printer->info_2, snum)) {
6611                 result = WERR_INVALID_PARAM;
6612                 goto done;
6613         }
6614
6615         /* FIXME!!! If the driver has changed we really should verify that
6616            it is installed before doing much else   --jerry */
6617
6618         /* Check calling user has permission to update printer description */
6619
6620         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6621                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6622                 result = WERR_ACCESS_DENIED;
6623                 goto done;
6624         }
6625
6626         /* Call addprinter hook */
6627         /* Check changes to see if this is really needed */
6628
6629         if ( *lp_addprinter_cmd()
6630                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6631                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6632                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6633                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6634         {
6635                 /* add_printer_hook() will call reload_services() */
6636
6637                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6638                                        printer) ) {
6639                         result = WERR_ACCESS_DENIED;
6640                         goto done;
6641                 }
6642         }
6643
6644         /*
6645          * When a *new* driver is bound to a printer, the drivername is used to
6646          * lookup previously saved driver initialization info, which is then
6647          * bound to the printer, simulating what happens in the Windows arch.
6648          */
6649         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6650         {
6651                 if (!set_driver_init(printer, 2))
6652                 {
6653                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6654                                 printer->info_2->drivername));
6655                 }
6656
6657                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6658                         printer->info_2->drivername));
6659
6660                 notify_printer_driver(snum, printer->info_2->drivername);
6661         }
6662
6663         /*
6664          * flag which changes actually occured.  This is a small subset of
6665          * all the possible changes.  We also have to update things in the
6666          * DsSpooler key.
6667          */
6668
6669         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6670                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6671                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6672                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6673
6674                 notify_printer_comment(snum, printer->info_2->comment);
6675         }
6676
6677         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6678                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6679                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6680                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6681
6682                 notify_printer_sharename(snum, printer->info_2->sharename);
6683         }
6684
6685         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6686                 char *pname;
6687
6688                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6689                         pname++;
6690                 else
6691                         pname = printer->info_2->printername;
6692
6693
6694                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6695                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6696                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6697
6698                 notify_printer_printername( snum, pname );
6699         }
6700
6701         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6702                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6703                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6704                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6705
6706                 notify_printer_port(snum, printer->info_2->portname);
6707         }
6708
6709         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6710                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6711                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6712                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6713
6714                 notify_printer_location(snum, printer->info_2->location);
6715         }
6716
6717         /* here we need to update some more DsSpooler keys */
6718         /* uNCName, serverName, shortServerName */
6719
6720         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6721         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6722                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6723         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6724                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6725
6726         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6727                  global_myname(), printer->info_2->sharename );
6728         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6729         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6730                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6731
6732         /* Update printer info */
6733         result = mod_a_printer(printer, 2);
6734
6735 done:
6736         free_a_printer(&printer, 2);
6737         free_a_printer(&old_printer, 2);
6738
6739
6740         return result;
6741 }
6742
6743 /****************************************************************************
6744 ****************************************************************************/
6745 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6746                                            struct spoolss_SetPrinterInfo7 *info7)
6747 {
6748 #ifdef HAVE_ADS
6749         int snum;
6750         Printer_entry *Printer;
6751
6752         if ( lp_security() != SEC_ADS ) {
6753                 return WERR_UNKNOWN_LEVEL;
6754         }
6755
6756         Printer = find_printer_index_by_hnd(p, handle);
6757
6758         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6759
6760         if (!Printer)
6761                 return WERR_BADFID;
6762
6763         if (!get_printer_snum(p, handle, &snum, NULL))
6764                 return WERR_BADFID;
6765
6766         nt_printer_publish(Printer, snum, info7->action);
6767
6768         return WERR_OK;
6769 #else
6770         return WERR_UNKNOWN_LEVEL;
6771 #endif
6772 }
6773
6774 /****************************************************************
6775  _spoolss_SetPrinter
6776 ****************************************************************/
6777
6778 WERROR _spoolss_SetPrinter(pipes_struct *p,
6779                            struct spoolss_SetPrinter *r)
6780 {
6781         POLICY_HND *handle = r->in.handle;
6782         WERROR result;
6783
6784         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6785
6786         if (!Printer) {
6787                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6788                         OUR_HANDLE(handle)));
6789                 return WERR_BADFID;
6790         }
6791
6792         /* check the level */
6793         switch (r->in.info_ctr->level) {
6794                 case 0:
6795                         return control_printer(handle, r->in.command, p);
6796                 case 2:
6797                         result = update_printer(p, handle,
6798                                                 r->in.info_ctr,
6799                                                 r->in.devmode_ctr->devmode);
6800                         if (!W_ERROR_IS_OK(result))
6801                                 return result;
6802                         if (r->in.secdesc_ctr->sd)
6803                                 result = update_printer_sec(handle, p,
6804                                                             r->in.secdesc_ctr);
6805                         return result;
6806                 case 3:
6807                         return update_printer_sec(handle, p,
6808                                                   r->in.secdesc_ctr);
6809                 case 7:
6810                         return publish_or_unpublish_printer(p, handle,
6811                                                             r->in.info_ctr->info.info7);
6812                 default:
6813                         return WERR_UNKNOWN_LEVEL;
6814         }
6815 }
6816
6817 /****************************************************************
6818  _spoolss_FindClosePrinterNotify
6819 ****************************************************************/
6820
6821 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6822                                        struct spoolss_FindClosePrinterNotify *r)
6823 {
6824         POLICY_HND *handle = r->in.handle;
6825         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6826
6827         if (!Printer) {
6828                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6829                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6830                 return WERR_BADFID;
6831         }
6832
6833         if (Printer->notify.client_connected==True) {
6834                 int snum = -1;
6835
6836                 if ( Printer->printer_type == SPLHND_SERVER)
6837                         snum = -1;
6838                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6839                                 !get_printer_snum(p, handle, &snum, NULL) )
6840                         return WERR_BADFID;
6841
6842                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6843         }
6844
6845         Printer->notify.flags=0;
6846         Printer->notify.options=0;
6847         Printer->notify.localmachine[0]='\0';
6848         Printer->notify.printerlocal=0;
6849         TALLOC_FREE(Printer->notify.option);
6850         Printer->notify.client_connected=False;
6851
6852         return WERR_OK;
6853 }
6854
6855 /****************************************************************
6856  _spoolss_AddJob
6857 ****************************************************************/
6858
6859 WERROR _spoolss_AddJob(pipes_struct *p,
6860                        struct spoolss_AddJob *r)
6861 {
6862         if (!r->in.buffer && (r->in.offered != 0)) {
6863                 return WERR_INVALID_PARAM;
6864         }
6865
6866         /* this is what a NT server returns for AddJob. AddJob must fail on
6867          * non-local printers */
6868
6869         if (r->in.level != 1) {
6870                 return WERR_UNKNOWN_LEVEL;
6871         }
6872
6873         return WERR_INVALID_PARAM;
6874 }
6875
6876 /****************************************************************************
6877 fill_job_info1
6878 ****************************************************************************/
6879
6880 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6881                              struct spoolss_JobInfo1 *r,
6882                              const print_queue_struct *queue,
6883                              int position, int snum,
6884                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6885 {
6886         struct tm *t;
6887
6888         t = gmtime(&queue->time);
6889
6890         r->job_id               = queue->job;
6891
6892         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6893         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6894         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6895         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6896         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6897         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6898         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6899         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6900         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6901         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6902         r->text_status          = talloc_strdup(mem_ctx, "");
6903         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6904
6905         r->status               = nt_printj_status(queue->status);
6906         r->priority             = queue->priority;
6907         r->position             = position;
6908         r->total_pages          = queue->page_count;
6909         r->pages_printed        = 0; /* ??? */
6910
6911         init_systemtime(&r->submitted, t);
6912
6913         return WERR_OK;
6914 }
6915
6916 /****************************************************************************
6917 fill_job_info2
6918 ****************************************************************************/
6919
6920 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6921                              struct spoolss_JobInfo2 *r,
6922                              const print_queue_struct *queue,
6923                              int position, int snum,
6924                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6925                              struct spoolss_DeviceMode *devmode)
6926 {
6927         struct tm *t;
6928
6929         t = gmtime(&queue->time);
6930
6931         r->job_id               = queue->job;
6932
6933         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6934         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6935         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6936         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6937         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6938         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6939         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6940         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6941         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6942         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6943         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6944         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6945         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6946         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6947         r->parameters           = talloc_strdup(mem_ctx, "");
6948         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6949         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6950         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6951
6952         r->devmode              = devmode;
6953
6954         r->text_status          = talloc_strdup(mem_ctx, "");
6955         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6956
6957         r->secdesc              = NULL;
6958
6959         r->status               = nt_printj_status(queue->status);
6960         r->priority             = queue->priority;
6961         r->position             = position;
6962         r->start_time           = 0;
6963         r->until_time           = 0;
6964         r->total_pages          = queue->page_count;
6965         r->size                 = queue->size;
6966         init_systemtime(&r->submitted, t);
6967         r->time                 = 0;
6968         r->pages_printed        = 0; /* ??? */
6969
6970         return WERR_OK;
6971 }
6972
6973 /****************************************************************************
6974  Enumjobs at level 1.
6975 ****************************************************************************/
6976
6977 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6978                               const print_queue_struct *queue,
6979                               uint32_t num_queues, int snum,
6980                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6981                               union spoolss_JobInfo **info_p,
6982                               uint32_t *count)
6983 {
6984         union spoolss_JobInfo *info;
6985         int i;
6986         WERROR result = WERR_OK;
6987
6988         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6989         W_ERROR_HAVE_NO_MEMORY(info);
6990
6991         *count = num_queues;
6992
6993         for (i=0; i<*count; i++) {
6994                 result = fill_job_info1(info,
6995                                         &info[i].info1,
6996                                         &queue[i],
6997                                         i,
6998                                         snum,
6999                                         ntprinter);
7000                 if (!W_ERROR_IS_OK(result)) {
7001                         goto out;
7002                 }
7003         }
7004
7005  out:
7006         if (!W_ERROR_IS_OK(result)) {
7007                 TALLOC_FREE(info);
7008                 *count = 0;
7009                 return result;
7010         }
7011
7012         *info_p = info;
7013
7014         return WERR_OK;
7015 }
7016
7017 /****************************************************************************
7018  Enumjobs at level 2.
7019 ****************************************************************************/
7020
7021 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7022                               const print_queue_struct *queue,
7023                               uint32_t num_queues, int snum,
7024                               const NT_PRINTER_INFO_LEVEL *ntprinter,
7025                               union spoolss_JobInfo **info_p,
7026                               uint32_t *count)
7027 {
7028         union spoolss_JobInfo *info;
7029         int i;
7030         WERROR result = WERR_OK;
7031
7032         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7033         W_ERROR_HAVE_NO_MEMORY(info);
7034
7035         *count = num_queues;
7036
7037         for (i=0; i<*count; i++) {
7038
7039                 struct spoolss_DeviceMode *devmode;
7040
7041                 devmode = construct_dev_mode_new(info, lp_const_servicename(snum));
7042                 if (!devmode) {
7043                         result = WERR_NOMEM;
7044                         goto out;
7045                 }
7046
7047                 result = fill_job_info2(info,
7048                                         &info[i].info2,
7049                                         &queue[i],
7050                                         i,
7051                                         snum,
7052                                         ntprinter,
7053                                         devmode);
7054                 if (!W_ERROR_IS_OK(result)) {
7055                         goto out;
7056                 }
7057         }
7058
7059  out:
7060         if (!W_ERROR_IS_OK(result)) {
7061                 TALLOC_FREE(info);
7062                 *count = 0;
7063                 return result;
7064         }
7065
7066         *info_p = info;
7067
7068         return WERR_OK;
7069 }
7070
7071 /****************************************************************
7072  _spoolss_EnumJobs
7073 ****************************************************************/
7074
7075 WERROR _spoolss_EnumJobs(pipes_struct *p,
7076                          struct spoolss_EnumJobs *r)
7077 {
7078         WERROR result;
7079         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
7080         int snum;
7081         print_status_struct prt_status;
7082         print_queue_struct *queue = NULL;
7083         uint32_t count;
7084
7085         /* that's an [in out] buffer */
7086
7087         if (!r->in.buffer && (r->in.offered != 0)) {
7088                 return WERR_INVALID_PARAM;
7089         }
7090
7091         DEBUG(4,("_spoolss_EnumJobs\n"));
7092
7093         *r->out.needed = 0;
7094         *r->out.count = 0;
7095         *r->out.info = NULL;
7096
7097         /* lookup the printer snum and tdb entry */
7098
7099         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7100                 return WERR_BADFID;
7101         }
7102
7103         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
7104         if (!W_ERROR_IS_OK(result)) {
7105                 return result;
7106         }
7107
7108         count = print_queue_status(snum, &queue, &prt_status);
7109         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7110                 count, prt_status.status, prt_status.message));
7111
7112         if (count == 0) {
7113                 SAFE_FREE(queue);
7114                 free_a_printer(&ntprinter, 2);
7115                 return WERR_OK;
7116         }
7117
7118         switch (r->in.level) {
7119         case 1:
7120                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7121                                          ntprinter, r->out.info, r->out.count);
7122                 break;
7123         case 2:
7124                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7125                                          ntprinter, r->out.info, r->out.count);
7126                 break;
7127         default:
7128                 result = WERR_UNKNOWN_LEVEL;
7129                 break;
7130         }
7131
7132         SAFE_FREE(queue);
7133         free_a_printer(&ntprinter, 2);
7134
7135         if (!W_ERROR_IS_OK(result)) {
7136                 return result;
7137         }
7138
7139         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7140                                                      spoolss_EnumJobs, NULL,
7141                                                      *r->out.info, r->in.level,
7142                                                      *r->out.count);
7143         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7144         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7145
7146         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7147 }
7148
7149 /****************************************************************
7150  _spoolss_ScheduleJob
7151 ****************************************************************/
7152
7153 WERROR _spoolss_ScheduleJob(pipes_struct *p,
7154                             struct spoolss_ScheduleJob *r)
7155 {
7156         return WERR_OK;
7157 }
7158
7159 /****************************************************************
7160  _spoolss_SetJob
7161 ****************************************************************/
7162
7163 WERROR _spoolss_SetJob(pipes_struct *p,
7164                        struct spoolss_SetJob *r)
7165 {
7166         POLICY_HND *handle = r->in.handle;
7167         uint32 jobid = r->in.job_id;
7168         uint32 command = r->in.command;
7169
7170         int snum;
7171         WERROR errcode = WERR_BADFUNC;
7172
7173         if (!get_printer_snum(p, handle, &snum, NULL)) {
7174                 return WERR_BADFID;
7175         }
7176
7177         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
7178                 return WERR_INVALID_PRINTER_NAME;
7179         }
7180
7181         switch (command) {
7182         case SPOOLSS_JOB_CONTROL_CANCEL:
7183         case SPOOLSS_JOB_CONTROL_DELETE:
7184                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
7185                         errcode = WERR_OK;
7186                 }
7187                 break;
7188         case SPOOLSS_JOB_CONTROL_PAUSE:
7189                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
7190                         errcode = WERR_OK;
7191                 }
7192                 break;
7193         case SPOOLSS_JOB_CONTROL_RESTART:
7194         case SPOOLSS_JOB_CONTROL_RESUME:
7195                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
7196                         errcode = WERR_OK;
7197                 }
7198                 break;
7199         default:
7200                 return WERR_UNKNOWN_LEVEL;
7201         }
7202
7203         return errcode;
7204 }
7205
7206 /****************************************************************************
7207  Enumerates all printer drivers at level 1.
7208 ****************************************************************************/
7209
7210 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
7211                                         const char *servername,
7212                                         const char *architecture,
7213                                         union spoolss_DriverInfo **info_p,
7214                                         uint32_t *count)
7215 {
7216         int i;
7217         int ndrivers;
7218         uint32_t version;
7219         fstring *list = NULL;
7220         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7221         union spoolss_DriverInfo *info = NULL;
7222         WERROR result = WERR_OK;
7223
7224         *count = 0;
7225
7226         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7227                 list = NULL;
7228                 ndrivers = get_ntdrivers(&list, architecture, version);
7229                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
7230                         ndrivers, architecture, version));
7231
7232                 if (ndrivers == -1) {
7233                         result = WERR_NOMEM;
7234                         goto out;
7235                 }
7236
7237                 if (ndrivers != 0) {
7238                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7239                                                     union spoolss_DriverInfo,
7240                                                     *count + ndrivers);
7241                         if (!info) {
7242                                 DEBUG(0,("enumprinterdrivers_level1: "
7243                                         "failed to enlarge driver info buffer!\n"));
7244                                 result = WERR_NOMEM;
7245                                 goto out;
7246                         }
7247                 }
7248
7249                 for (i=0; i<ndrivers; i++) {
7250                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7251                         ZERO_STRUCT(driver);
7252                         result = get_a_printer_driver(&driver, 3, list[i],
7253                                                       architecture, version);
7254                         if (!W_ERROR_IS_OK(result)) {
7255                                 goto out;
7256                         }
7257                         result = fill_printer_driver_info1(info, &info[*count+i].info1,
7258                                                            &driver, servername,
7259                                                            architecture);
7260                         if (!W_ERROR_IS_OK(result)) {
7261                                 free_a_printer_driver(driver, 3);
7262                                 goto out;
7263                         }
7264                         free_a_printer_driver(driver, 3);
7265                 }
7266
7267                 *count += ndrivers;
7268                 SAFE_FREE(list);
7269         }
7270
7271  out:
7272         SAFE_FREE(list);
7273
7274         if (!W_ERROR_IS_OK(result)) {
7275                 TALLOC_FREE(info);
7276                 *count = 0;
7277                 return result;
7278         }
7279
7280         *info_p = info;
7281
7282         return WERR_OK;
7283 }
7284
7285 /****************************************************************************
7286  Enumerates all printer drivers at level 2.
7287 ****************************************************************************/
7288
7289 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
7290                                         const char *servername,
7291                                         const char *architecture,
7292                                         union spoolss_DriverInfo **info_p,
7293                                         uint32_t *count)
7294 {
7295         int i;
7296         int ndrivers;
7297         uint32_t version;
7298         fstring *list = NULL;
7299         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7300         union spoolss_DriverInfo *info = NULL;
7301         WERROR result = WERR_OK;
7302
7303         *count = 0;
7304
7305         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7306                 list = NULL;
7307                 ndrivers = get_ntdrivers(&list, architecture, version);
7308                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
7309                         ndrivers, architecture, version));
7310
7311                 if (ndrivers == -1) {
7312                         result = WERR_NOMEM;
7313                         goto out;
7314                 }
7315
7316                 if (ndrivers != 0) {
7317                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7318                                                     union spoolss_DriverInfo,
7319                                                     *count + ndrivers);
7320                         if (!info) {
7321                                 DEBUG(0,("enumprinterdrivers_level2: "
7322                                         "failed to enlarge driver info buffer!\n"));
7323                                 result = WERR_NOMEM;
7324                                 goto out;
7325                         }
7326                 }
7327
7328                 for (i=0; i<ndrivers; i++) {
7329                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7330                         ZERO_STRUCT(driver);
7331                         result = get_a_printer_driver(&driver, 3, list[i],
7332                                                       architecture, version);
7333                         if (!W_ERROR_IS_OK(result)) {
7334                                 goto out;
7335                         }
7336                         result = fill_printer_driver_info2(info, &info[*count+i].info2,
7337                                                            &driver, servername);
7338                         if (!W_ERROR_IS_OK(result)) {
7339                                 free_a_printer_driver(driver, 3);
7340                                 goto out;
7341                         }
7342                         free_a_printer_driver(driver, 3);
7343                 }
7344
7345                 *count += ndrivers;
7346                 SAFE_FREE(list);
7347         }
7348
7349  out:
7350         SAFE_FREE(list);
7351
7352         if (!W_ERROR_IS_OK(result)) {
7353                 TALLOC_FREE(info);
7354                 *count = 0;
7355                 return result;
7356         }
7357
7358         *info_p = info;
7359
7360         return WERR_OK;
7361 }
7362
7363 /****************************************************************************
7364  Enumerates all printer drivers at level 3.
7365 ****************************************************************************/
7366
7367 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
7368                                         const char *servername,
7369                                         const char *architecture,
7370                                         union spoolss_DriverInfo **info_p,
7371                                         uint32_t *count)
7372 {
7373         int i;
7374         int ndrivers;
7375         uint32_t version;
7376         fstring *list = NULL;
7377         union spoolss_DriverInfo *info = NULL;
7378         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7379         WERROR result = WERR_OK;
7380
7381         *count = 0;
7382
7383         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7384                 list = NULL;
7385                 ndrivers = get_ntdrivers(&list, architecture, version);
7386                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
7387                         ndrivers, architecture, version));
7388
7389                 if (ndrivers == -1) {
7390                         result = WERR_NOMEM;
7391                         goto out;
7392                 }
7393
7394                 if (ndrivers != 0) {
7395                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7396                                                     union spoolss_DriverInfo,
7397                                                     *count + ndrivers);
7398                         if (!info) {
7399                                 DEBUG(0,("enumprinterdrivers_level3: "
7400                                         "failed to enlarge driver info buffer!\n"));
7401                                 result = WERR_NOMEM;
7402                                 goto out;
7403                         }
7404                 }
7405
7406                 for (i=0; i<ndrivers; i++) {
7407                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7408                         ZERO_STRUCT(driver);
7409                         result = get_a_printer_driver(&driver, 3, list[i],
7410                                                       architecture, version);
7411                         if (!W_ERROR_IS_OK(result)) {
7412                                 goto out;
7413                         }
7414                         result = fill_printer_driver_info3(info, &info[*count+i].info3,
7415                                                            &driver, servername);
7416                         if (!W_ERROR_IS_OK(result)) {
7417                                 free_a_printer_driver(driver, 3);
7418                                 goto out;
7419                         }
7420
7421                         free_a_printer_driver(driver, 3);
7422                 }
7423
7424                 *count += ndrivers;
7425                 SAFE_FREE(list);
7426         }
7427
7428  out:
7429         SAFE_FREE(list);
7430
7431         if (!W_ERROR_IS_OK(result)) {
7432                 TALLOC_FREE(info);
7433                 *count = 0;
7434                 return result;
7435         }
7436
7437         *info_p = info;
7438
7439         return WERR_OK;
7440 }
7441
7442 /****************************************************************
7443  _spoolss_EnumPrinterDrivers
7444 ****************************************************************/
7445
7446 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
7447                                    struct spoolss_EnumPrinterDrivers *r)
7448 {
7449         const char *cservername;
7450         WERROR result;
7451
7452         /* that's an [in out] buffer */
7453
7454         if (!r->in.buffer && (r->in.offered != 0)) {
7455                 return WERR_INVALID_PARAM;
7456         }
7457
7458         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7459
7460         *r->out.needed = 0;
7461         *r->out.count = 0;
7462         *r->out.info = NULL;
7463
7464         cservername = canon_servername(r->in.server);
7465
7466         if (!is_myname_or_ipaddr(cservername)) {
7467                 return WERR_UNKNOWN_PRINTER_DRIVER;
7468         }
7469
7470         switch (r->in.level) {
7471         case 1:
7472                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
7473                                                    r->in.environment,
7474                                                    r->out.info, r->out.count);
7475                 break;
7476         case 2:
7477                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
7478                                                    r->in.environment,
7479                                                    r->out.info, r->out.count);
7480                 break;
7481         case 3:
7482                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
7483                                                    r->in.environment,
7484                                                    r->out.info, r->out.count);
7485                 break;
7486         default:
7487                 return WERR_UNKNOWN_LEVEL;
7488         }
7489
7490         if (!W_ERROR_IS_OK(result)) {
7491                 return result;
7492         }
7493
7494         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7495                                                      spoolss_EnumPrinterDrivers, NULL,
7496                                                      *r->out.info, r->in.level,
7497                                                      *r->out.count);
7498         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7499         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7500
7501         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7502 }
7503
7504 /****************************************************************************
7505 ****************************************************************************/
7506
7507 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7508                                struct spoolss_FormInfo1 *r,
7509                                const nt_forms_struct *form)
7510 {
7511         r->form_name    = talloc_strdup(mem_ctx, form->name);
7512         W_ERROR_HAVE_NO_MEMORY(r->form_name);
7513
7514         r->flags        = form->flag;
7515         r->size.width   = form->width;
7516         r->size.height  = form->length;
7517         r->area.left    = form->left;
7518         r->area.top     = form->top;
7519         r->area.right   = form->right;
7520         r->area.bottom  = form->bottom;
7521
7522         return WERR_OK;
7523 }
7524
7525 /****************************************************************
7526  spoolss_enumforms_level1
7527 ****************************************************************/
7528
7529 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7530                                        const nt_forms_struct *builtin_forms,
7531                                        uint32_t num_builtin_forms,
7532                                        const nt_forms_struct *user_forms,
7533                                        uint32_t num_user_forms,
7534                                        union spoolss_FormInfo **info_p,
7535                                        uint32_t *count)
7536 {
7537         union spoolss_FormInfo *info;
7538         WERROR result = WERR_OK;
7539         int i;
7540
7541         *count = num_builtin_forms + num_user_forms;
7542
7543         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7544         W_ERROR_HAVE_NO_MEMORY(info);
7545
7546         /* construct the list of form structures */
7547         for (i=0; i<num_builtin_forms; i++) {
7548                 DEBUGADD(6,("Filling form number [%d]\n",i));
7549                 result = fill_form_info_1(info, &info[i].info1,
7550                                           &builtin_forms[i]);
7551                 if (!W_ERROR_IS_OK(result)) {
7552                         goto out;
7553                 }
7554         }
7555
7556         for (; i<num_user_forms; i++) {
7557                 DEBUGADD(6,("Filling form number [%d]\n",i));
7558                 result = fill_form_info_1(info, &info[i].info1,
7559                                           &user_forms[i-num_builtin_forms]);
7560                 if (!W_ERROR_IS_OK(result)) {
7561                         goto out;
7562                 }
7563         }
7564
7565  out:
7566         if (!W_ERROR_IS_OK(result)) {
7567                 TALLOC_FREE(info);
7568                 *count = 0;
7569                 return result;
7570         }
7571
7572         *info_p = info;
7573
7574         return WERR_OK;
7575 }
7576
7577 /****************************************************************
7578  _spoolss_EnumForms
7579 ****************************************************************/
7580
7581 WERROR _spoolss_EnumForms(pipes_struct *p,
7582                           struct spoolss_EnumForms *r)
7583 {
7584         WERROR result;
7585         nt_forms_struct *user_forms = NULL;
7586         nt_forms_struct *builtin_forms = NULL;
7587         uint32_t num_user_forms;
7588         uint32_t num_builtin_forms;
7589
7590         *r->out.count = 0;
7591         *r->out.needed = 0;
7592         *r->out.info = NULL;
7593
7594         /* that's an [in out] buffer */
7595
7596         if (!r->in.buffer && (r->in.offered != 0) ) {
7597                 return WERR_INVALID_PARAM;
7598         }
7599
7600         DEBUG(4,("_spoolss_EnumForms\n"));
7601         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7602         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7603
7604         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7605         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7606         num_user_forms = get_ntforms(&user_forms);
7607         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7608
7609         if (num_user_forms + num_builtin_forms == 0) {
7610                 SAFE_FREE(builtin_forms);
7611                 SAFE_FREE(user_forms);
7612                 return WERR_NO_MORE_ITEMS;
7613         }
7614
7615         switch (r->in.level) {
7616         case 1:
7617                 result = spoolss_enumforms_level1(p->mem_ctx,
7618                                                   builtin_forms,
7619                                                   num_builtin_forms,
7620                                                   user_forms,
7621                                                   num_user_forms,
7622                                                   r->out.info,
7623                                                   r->out.count);
7624                 break;
7625         default:
7626                 result = WERR_UNKNOWN_LEVEL;
7627                 break;
7628         }
7629
7630         SAFE_FREE(user_forms);
7631         SAFE_FREE(builtin_forms);
7632
7633         if (!W_ERROR_IS_OK(result)) {
7634                 return result;
7635         }
7636
7637         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7638                                                      spoolss_EnumForms, NULL,
7639                                                      *r->out.info, r->in.level,
7640                                                      *r->out.count);
7641         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7642         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7643
7644         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7645 }
7646
7647 /****************************************************************
7648 ****************************************************************/
7649
7650 static WERROR find_form_byname(const char *name,
7651                                nt_forms_struct *form)
7652 {
7653         nt_forms_struct *list = NULL;
7654         int num_forms = 0, i = 0;
7655
7656         if (get_a_builtin_ntform_by_string(name, form)) {
7657                 return WERR_OK;
7658         }
7659
7660         num_forms = get_ntforms(&list);
7661         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7662
7663         if (num_forms == 0) {
7664                 return WERR_BADFID;
7665         }
7666
7667         /* Check if the requested name is in the list of form structures */
7668         for (i = 0; i < num_forms; i++) {
7669
7670                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7671
7672                 if (strequal(name, list[i].name)) {
7673                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7674                         *form = list[i];
7675                         SAFE_FREE(list);
7676                         return WERR_OK;
7677                 }
7678         }
7679
7680         SAFE_FREE(list);
7681
7682         return WERR_BADFID;
7683 }
7684
7685 /****************************************************************
7686  _spoolss_GetForm
7687 ****************************************************************/
7688
7689 WERROR _spoolss_GetForm(pipes_struct *p,
7690                         struct spoolss_GetForm *r)
7691 {
7692         WERROR result;
7693         nt_forms_struct form;
7694
7695         /* that's an [in out] buffer */
7696
7697         if (!r->in.buffer && (r->in.offered != 0)) {
7698                 return WERR_INVALID_PARAM;
7699         }
7700
7701         DEBUG(4,("_spoolss_GetForm\n"));
7702         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7703         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7704
7705         result = find_form_byname(r->in.form_name, &form);
7706         if (!W_ERROR_IS_OK(result)) {
7707                 TALLOC_FREE(r->out.info);
7708                 return result;
7709         }
7710
7711         switch (r->in.level) {
7712         case 1:
7713                 result = fill_form_info_1(p->mem_ctx,
7714                                           &r->out.info->info1,
7715                                           &form);
7716                 break;
7717
7718         default:
7719                 result = WERR_UNKNOWN_LEVEL;
7720                 break;
7721         }
7722
7723         if (!W_ERROR_IS_OK(result)) {
7724                 TALLOC_FREE(r->out.info);
7725                 return result;
7726         }
7727
7728         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7729                                                r->out.info, r->in.level);
7730         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7731
7732         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7733 }
7734
7735 /****************************************************************************
7736 ****************************************************************************/
7737
7738 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7739                           struct spoolss_PortInfo1 *r,
7740                           const char *name)
7741 {
7742         r->port_name = talloc_strdup(mem_ctx, name);
7743         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7744
7745         return WERR_OK;
7746 }
7747
7748 /****************************************************************************
7749  TODO: This probably needs distinguish between TCP/IP and Local ports
7750  somehow.
7751 ****************************************************************************/
7752
7753 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7754                           struct spoolss_PortInfo2 *r,
7755                           const char *name)
7756 {
7757         r->port_name = talloc_strdup(mem_ctx, name);
7758         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7759
7760         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7761         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7762
7763         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7764         W_ERROR_HAVE_NO_MEMORY(r->description);
7765
7766         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7767         r->reserved = 0;
7768
7769         return WERR_OK;
7770 }
7771
7772
7773 /****************************************************************************
7774  wrapper around the enumer ports command
7775 ****************************************************************************/
7776
7777 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7778 {
7779         char *cmd = lp_enumports_cmd();
7780         char **qlines = NULL;
7781         char *command = NULL;
7782         int numlines;
7783         int ret;
7784         int fd;
7785
7786         *count = 0;
7787         *lines = NULL;
7788
7789         /* if no hook then just fill in the default port */
7790
7791         if ( !*cmd ) {
7792                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7793                         return WERR_NOMEM;
7794                 }
7795                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7796                         TALLOC_FREE(qlines);
7797                         return WERR_NOMEM;
7798                 }
7799                 qlines[1] = NULL;
7800                 numlines = 1;
7801         }
7802         else {
7803                 /* we have a valid enumport command */
7804
7805                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7806                 if (!command) {
7807                         return WERR_NOMEM;
7808                 }
7809
7810                 DEBUG(10,("Running [%s]\n", command));
7811                 ret = smbrun(command, &fd);
7812                 DEBUG(10,("Returned [%d]\n", ret));
7813                 TALLOC_FREE(command);
7814                 if (ret != 0) {
7815                         if (fd != -1) {
7816                                 close(fd);
7817                         }
7818                         return WERR_ACCESS_DENIED;
7819                 }
7820
7821                 numlines = 0;
7822                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7823                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7824                 close(fd);
7825         }
7826
7827         *count = numlines;
7828         *lines = qlines;
7829
7830         return WERR_OK;
7831 }
7832
7833 /****************************************************************************
7834  enumports level 1.
7835 ****************************************************************************/
7836
7837 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7838                                 union spoolss_PortInfo **info_p,
7839                                 uint32_t *count)
7840 {
7841         union spoolss_PortInfo *info = NULL;
7842         int i=0;
7843         WERROR result = WERR_OK;
7844         char **qlines = NULL;
7845         int numlines = 0;
7846
7847         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7848         if (!W_ERROR_IS_OK(result)) {
7849                 goto out;
7850         }
7851
7852         if (numlines) {
7853                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7854                 if (!info) {
7855                         DEBUG(10,("Returning WERR_NOMEM\n"));
7856                         result = WERR_NOMEM;
7857                         goto out;
7858                 }
7859
7860                 for (i=0; i<numlines; i++) {
7861                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7862                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7863                         if (!W_ERROR_IS_OK(result)) {
7864                                 goto out;
7865                         }
7866                 }
7867         }
7868         TALLOC_FREE(qlines);
7869
7870 out:
7871         if (!W_ERROR_IS_OK(result)) {
7872                 TALLOC_FREE(info);
7873                 TALLOC_FREE(qlines);
7874                 *count = 0;
7875                 *info_p = NULL;
7876                 return result;
7877         }
7878
7879         *info_p = info;
7880         *count = numlines;
7881
7882         return WERR_OK;
7883 }
7884
7885 /****************************************************************************
7886  enumports level 2.
7887 ****************************************************************************/
7888
7889 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7890                                 union spoolss_PortInfo **info_p,
7891                                 uint32_t *count)
7892 {
7893         union spoolss_PortInfo *info = NULL;
7894         int i=0;
7895         WERROR result = WERR_OK;
7896         char **qlines = NULL;
7897         int numlines = 0;
7898
7899         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7900         if (!W_ERROR_IS_OK(result)) {
7901                 goto out;
7902         }
7903
7904         if (numlines) {
7905                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7906                 if (!info) {
7907                         DEBUG(10,("Returning WERR_NOMEM\n"));
7908                         result = WERR_NOMEM;
7909                         goto out;
7910                 }
7911
7912                 for (i=0; i<numlines; i++) {
7913                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7914                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7915                         if (!W_ERROR_IS_OK(result)) {
7916                                 goto out;
7917                         }
7918                 }
7919         }
7920         TALLOC_FREE(qlines);
7921
7922 out:
7923         if (!W_ERROR_IS_OK(result)) {
7924                 TALLOC_FREE(info);
7925                 TALLOC_FREE(qlines);
7926                 *count = 0;
7927                 *info_p = NULL;
7928                 return result;
7929         }
7930
7931         *info_p = info;
7932         *count = numlines;
7933
7934         return WERR_OK;
7935 }
7936
7937 /****************************************************************
7938  _spoolss_EnumPorts
7939 ****************************************************************/
7940
7941 WERROR _spoolss_EnumPorts(pipes_struct *p,
7942                           struct spoolss_EnumPorts *r)
7943 {
7944         WERROR result;
7945
7946         /* that's an [in out] buffer */
7947
7948         if (!r->in.buffer && (r->in.offered != 0)) {
7949                 return WERR_INVALID_PARAM;
7950         }
7951
7952         DEBUG(4,("_spoolss_EnumPorts\n"));
7953
7954         *r->out.count = 0;
7955         *r->out.needed = 0;
7956         *r->out.info = NULL;
7957
7958         switch (r->in.level) {
7959         case 1:
7960                 result = enumports_level_1(p->mem_ctx, r->out.info,
7961                                            r->out.count);
7962                 break;
7963         case 2:
7964                 result = enumports_level_2(p->mem_ctx, r->out.info,
7965                                            r->out.count);
7966                 break;
7967         default:
7968                 return WERR_UNKNOWN_LEVEL;
7969         }
7970
7971         if (!W_ERROR_IS_OK(result)) {
7972                 return result;
7973         }
7974
7975         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7976                                                      spoolss_EnumPorts, NULL,
7977                                                      *r->out.info, r->in.level,
7978                                                      *r->out.count);
7979         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7980         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7981
7982         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7983 }
7984
7985 /****************************************************************************
7986 ****************************************************************************/
7987
7988 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7989                                            const char *server,
7990                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7991                                            struct spoolss_DeviceMode *devmode,
7992                                            struct security_descriptor *sec_desc,
7993                                            struct spoolss_UserLevelCtr *user_ctr,
7994                                            POLICY_HND *handle)
7995 {
7996         NT_PRINTER_INFO_LEVEL *printer = NULL;
7997         fstring name;
7998         int     snum;
7999         WERROR err = WERR_OK;
8000
8001         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
8002                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
8003                 return WERR_NOMEM;
8004         }
8005
8006         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
8007         if (!convert_printer_info_new(info_ctr, printer)) {
8008                 free_a_printer(&printer, 2);
8009                 return WERR_NOMEM;
8010         }
8011
8012         /* check to see if the printer already exists */
8013
8014         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
8015                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8016                         printer->info_2->sharename));
8017                 free_a_printer(&printer, 2);
8018                 return WERR_PRINTER_ALREADY_EXISTS;
8019         }
8020
8021         /* FIXME!!!  smbd should check to see if the driver is installed before
8022            trying to add a printer like this  --jerry */
8023
8024         if (*lp_addprinter_cmd() ) {
8025                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
8026                                        printer) ) {
8027                         free_a_printer(&printer,2);
8028                         return WERR_ACCESS_DENIED;
8029                 }
8030         } else {
8031                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
8032                         "smb.conf parameter \"addprinter command\" is defined. This"
8033                         "parameter must exist for this call to succeed\n",
8034                         printer->info_2->sharename ));
8035         }
8036
8037         /* use our primary netbios name since get_a_printer() will convert
8038            it to what the client expects on a case by case basis */
8039
8040         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
8041              printer->info_2->sharename);
8042
8043
8044         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
8045                 free_a_printer(&printer,2);
8046                 return WERR_ACCESS_DENIED;
8047         }
8048
8049         /* you must be a printer admin to add a new printer */
8050         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
8051                 free_a_printer(&printer,2);
8052                 return WERR_ACCESS_DENIED;
8053         }
8054
8055         /*
8056          * Do sanity check on the requested changes for Samba.
8057          */
8058
8059         if (!check_printer_ok(printer->info_2, snum)) {
8060                 free_a_printer(&printer,2);
8061                 return WERR_INVALID_PARAM;
8062         }
8063
8064         /*
8065          * When a printer is created, the drivername bound to the printer is used
8066          * to lookup previously saved driver initialization info, which is then
8067          * bound to the new printer, simulating what happens in the Windows arch.
8068          */
8069
8070         if (!devmode)
8071         {
8072                 set_driver_init(printer, 2);
8073         }
8074         else
8075         {
8076                 /* A valid devmode was included, convert and link it
8077                 */
8078                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
8079
8080                 if (!convert_devicemode_new(printer->info_2->printername,
8081                                             devmode,
8082                                             &printer->info_2->devmode))
8083                         return  WERR_NOMEM;
8084         }
8085
8086         /* write the ASCII on disk */
8087         err = mod_a_printer(printer, 2);
8088         if (!W_ERROR_IS_OK(err)) {
8089                 free_a_printer(&printer,2);
8090                 return err;
8091         }
8092
8093         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
8094                 /* Handle open failed - remove addition. */
8095                 del_a_printer(printer->info_2->sharename);
8096                 free_a_printer(&printer,2);
8097                 ZERO_STRUCTP(handle);
8098                 return WERR_ACCESS_DENIED;
8099         }
8100
8101         update_c_setprinter(False);
8102         free_a_printer(&printer,2);
8103
8104         return WERR_OK;
8105 }
8106
8107 /****************************************************************
8108  _spoolss_AddPrinterEx
8109 ****************************************************************/
8110
8111 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
8112                              struct spoolss_AddPrinterEx *r)
8113 {
8114         switch (r->in.info_ctr->level) {
8115         case 1:
8116                 /* we don't handle yet */
8117                 /* but I know what to do ... */
8118                 return WERR_UNKNOWN_LEVEL;
8119         case 2:
8120                 return spoolss_addprinterex_level_2(p, r->in.server,
8121                                                     r->in.info_ctr,
8122                                                     r->in.devmode_ctr->devmode,
8123                                                     r->in.secdesc_ctr->sd,
8124                                                     r->in.userlevel_ctr,
8125                                                     r->out.handle);
8126         default:
8127                 return WERR_UNKNOWN_LEVEL;
8128         }
8129 }
8130
8131 /****************************************************************
8132  _spoolss_AddPrinterDriver
8133 ****************************************************************/
8134
8135 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
8136                                  struct spoolss_AddPrinterDriver *r)
8137 {
8138         uint32_t level = r->in.info_ctr->level;
8139         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
8140         WERROR err = WERR_OK;
8141         NT_PRINTER_DRIVER_INFO_LEVEL driver;
8142         fstring driver_name;
8143         uint32 version;
8144         const char *fn;
8145
8146         switch (p->hdr_req.opnum) {
8147                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8148                         fn = "_spoolss_AddPrinterDriver";
8149                         break;
8150                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8151                         fn = "_spoolss_AddPrinterDriverEx";
8152                         break;
8153                 default:
8154                         return WERR_INVALID_PARAM;
8155         }
8156
8157
8158         /* FIXME */
8159         if (level != 3 && level != 6) {
8160                 /* Clever hack from Martin Zielinski <mz@seh.de>
8161                  * to allow downgrade from level 8 (Vista).
8162                  */
8163                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
8164                 return WERR_UNKNOWN_LEVEL;
8165         }
8166
8167         ZERO_STRUCT(driver);
8168
8169         if (!convert_printer_driver_info(info, &driver, level)) {
8170                 err = WERR_NOMEM;
8171                 goto done;
8172         }
8173
8174         DEBUG(5,("Cleaning driver's information\n"));
8175         err = clean_up_driver_struct(p, driver, level);
8176         if (!W_ERROR_IS_OK(err))
8177                 goto done;
8178
8179         DEBUG(5,("Moving driver to final destination\n"));
8180         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
8181                                                               &err)) ) {
8182                 goto done;
8183         }
8184
8185         if (add_a_printer_driver(driver, level)!=0) {
8186                 err = WERR_ACCESS_DENIED;
8187                 goto done;
8188         }
8189
8190         switch(level) {
8191         case 3:
8192                 fstrcpy(driver_name,
8193                         driver.info_3->name ? driver.info_3->name : "");
8194                 break;
8195         case 6:
8196                 fstrcpy(driver_name,
8197                         driver.info_6->name ?  driver.info_6->name : "");
8198                 break;
8199         }
8200
8201         /*
8202          * I think this is where he DrvUpgradePrinter() hook would be
8203          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8204          * server.  Right now, we just need to send ourselves a message
8205          * to update each printer bound to this driver.   --jerry
8206          */
8207
8208         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
8209                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8210                         fn, driver_name));
8211         }
8212
8213         /*
8214          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
8215          * decide if the driver init data should be deleted. The rules are:
8216          *  1) never delete init data if it is a 9x driver, they don't use it anyway
8217          *  2) delete init data only if there is no 2k/Xp driver
8218          *  3) always delete init data
8219          * The generalized rule is always use init data from the highest order driver.
8220          * It is necessary to follow the driver install by an initialization step to
8221          * finish off this process.
8222         */
8223         if (level == 3)
8224                 version = driver.info_3->cversion;
8225         else if (level == 6)
8226                 version = driver.info_6->version;
8227         else
8228                 version = -1;
8229         switch (version) {
8230                 /*
8231                  * 9x printer driver - never delete init data
8232                 */
8233                 case 0:
8234                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
8235                                 fn, driver_name));
8236                         break;
8237
8238                 /*
8239                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
8240                  * there is no 2k/Xp driver init data for this driver name.
8241                 */
8242                 case 2:
8243                 {
8244                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
8245
8246                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
8247                                 /*
8248                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8249                                 */
8250                                 if (!del_driver_init(driver_name))
8251                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
8252                                                 fn, driver_name));
8253                         } else {
8254                                 /*
8255                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8256                                 */
8257                                 free_a_printer_driver(driver1,3);
8258                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
8259                                         fn, driver_name));
8260                         }
8261                 }
8262                 break;
8263
8264                 /*
8265                  * 2k or Xp printer driver - always delete init data
8266                 */
8267                 case 3:
8268                         if (!del_driver_init(driver_name))
8269                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8270                                         fn, driver_name));
8271                         break;
8272
8273                 default:
8274                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
8275                         break;
8276         }
8277
8278
8279 done:
8280         free_a_printer_driver(driver, level);
8281         return err;
8282 }
8283
8284 /****************************************************************
8285  _spoolss_AddPrinterDriverEx
8286 ****************************************************************/
8287
8288 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8289                                    struct spoolss_AddPrinterDriverEx *r)
8290 {
8291         struct spoolss_AddPrinterDriver a;
8292
8293         /*
8294          * we only support the semantics of AddPrinterDriver()
8295          * i.e. only copy files that are newer than existing ones
8296          */
8297
8298         if (r->in.flags != APD_COPY_NEW_FILES) {
8299                 return WERR_ACCESS_DENIED;
8300         }
8301
8302         a.in.servername         = r->in.servername;
8303         a.in.info_ctr           = r->in.info_ctr;
8304
8305         return _spoolss_AddPrinterDriver(p, &a);
8306 }
8307
8308 /****************************************************************************
8309 ****************************************************************************/
8310
8311 struct _spoolss_paths {
8312         int type;
8313         const char *share;
8314         const char *dir;
8315 };
8316
8317 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8318
8319 static const struct _spoolss_paths spoolss_paths[]= {
8320         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8321         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8322 };
8323
8324 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8325                                           const char *servername,
8326                                           const char *environment,
8327                                           int component,
8328                                           char **path)
8329 {
8330         const char *pservername = NULL;
8331         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8332         const char *short_archi;
8333
8334         *path = NULL;
8335
8336         /* environment may be empty */
8337         if (environment && strlen(environment)) {
8338                 long_archi = environment;
8339         }
8340
8341         /* servername may be empty */
8342         if (servername && strlen(servername)) {
8343                 pservername = canon_servername(servername);
8344
8345                 if (!is_myname_or_ipaddr(pservername)) {
8346                         return WERR_INVALID_PARAM;
8347                 }
8348         }
8349
8350         if (!(short_archi = get_short_archi(long_archi))) {
8351                 return WERR_INVALID_ENVIRONMENT;
8352         }
8353
8354         switch (component) {
8355         case SPOOLSS_PRTPROCS_PATH:
8356         case SPOOLSS_DRIVER_PATH:
8357                 if (pservername) {
8358                         *path = talloc_asprintf(mem_ctx,
8359                                         "\\\\%s\\%s\\%s",
8360                                         pservername,
8361                                         spoolss_paths[component].share,
8362                                         short_archi);
8363                 } else {
8364                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8365                                         SPOOLSS_DEFAULT_SERVER_PATH,
8366                                         spoolss_paths[component].dir,
8367                                         short_archi);
8368                 }
8369                 break;
8370         default:
8371                 return WERR_INVALID_PARAM;
8372         }
8373
8374         if (!*path) {
8375                 return WERR_NOMEM;
8376         }
8377
8378         return WERR_OK;
8379 }
8380
8381 /****************************************************************************
8382 ****************************************************************************/
8383
8384 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8385                                           const char *servername,
8386                                           const char *environment,
8387                                           struct spoolss_DriverDirectoryInfo1 *r)
8388 {
8389         WERROR werr;
8390         char *path = NULL;
8391
8392         werr = compose_spoolss_server_path(mem_ctx,
8393                                            servername,
8394                                            environment,
8395                                            SPOOLSS_DRIVER_PATH,
8396                                            &path);
8397         if (!W_ERROR_IS_OK(werr)) {
8398                 return werr;
8399         }
8400
8401         DEBUG(4,("printer driver directory: [%s]\n", path));
8402
8403         r->directory_name = path;
8404
8405         return WERR_OK;
8406 }
8407
8408 /****************************************************************
8409  _spoolss_GetPrinterDriverDirectory
8410 ****************************************************************/
8411
8412 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8413                                           struct spoolss_GetPrinterDriverDirectory *r)
8414 {
8415         WERROR werror;
8416
8417         /* that's an [in out] buffer */
8418
8419         if (!r->in.buffer && (r->in.offered != 0)) {
8420                 return WERR_INVALID_PARAM;
8421         }
8422
8423         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8424                 r->in.level));
8425
8426         *r->out.needed = 0;
8427
8428         /* r->in.level is ignored */
8429
8430         werror = getprinterdriverdir_level_1(p->mem_ctx,
8431                                              r->in.server,
8432                                              r->in.environment,
8433                                              &r->out.info->info1);
8434         if (!W_ERROR_IS_OK(werror)) {
8435                 TALLOC_FREE(r->out.info);
8436                 return werror;
8437         }
8438
8439         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
8440                                                r->out.info, r->in.level);
8441         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8442
8443         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8444 }
8445
8446 /****************************************************************************
8447 ****************************************************************************/
8448
8449 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8450 {
8451         POLICY_HND *handle = &q_u->handle;
8452         uint32 idx               = q_u->index;
8453         uint32 in_value_len      = q_u->valuesize;
8454         uint32 in_data_len       = q_u->datasize;
8455         uint32 *out_max_value_len = &r_u->valuesize;
8456         uint16 **out_value       = &r_u->value;
8457         uint32 *out_value_len    = &r_u->realvaluesize;
8458         uint32 *out_type         = &r_u->type;
8459         uint32 *out_max_data_len = &r_u->datasize;
8460         uint8  **data_out        = &r_u->data;
8461         uint32 *out_data_len     = &r_u->realdatasize;
8462
8463         NT_PRINTER_INFO_LEVEL *printer = NULL;
8464
8465         uint32          biggest_valuesize;
8466         uint32          biggest_datasize;
8467         uint32          data_len;
8468         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8469         int             snum;
8470         WERROR          result;
8471         REGISTRY_VALUE  *val = NULL;
8472         NT_PRINTER_DATA *p_data;
8473         int             i, key_index, num_values;
8474         int             name_length;
8475
8476         *out_type = 0;
8477
8478         *out_max_data_len = 0;
8479         *data_out         = NULL;
8480         *out_data_len     = 0;
8481
8482         DEBUG(5,("spoolss_enumprinterdata\n"));
8483
8484         if (!Printer) {
8485                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8486                 return WERR_BADFID;
8487         }
8488
8489         if (!get_printer_snum(p,handle, &snum, NULL))
8490                 return WERR_BADFID;
8491
8492         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8493         if (!W_ERROR_IS_OK(result))
8494                 return result;
8495
8496         p_data = printer->info_2->data;
8497         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8498
8499         result = WERR_OK;
8500
8501         /*
8502          * The NT machine wants to know the biggest size of value and data
8503          *
8504          * cf: MSDN EnumPrinterData remark section
8505          */
8506
8507         if ( !in_value_len && !in_data_len && (key_index != -1) )
8508         {
8509                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8510
8511                 biggest_valuesize = 0;
8512                 biggest_datasize  = 0;
8513
8514                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8515
8516                 for ( i=0; i<num_values; i++ )
8517                 {
8518                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8519
8520                         name_length = strlen(val->valuename);
8521                         if ( strlen(val->valuename) > biggest_valuesize )
8522                                 biggest_valuesize = name_length;
8523
8524                         if ( val->size > biggest_datasize )
8525                                 biggest_datasize = val->size;
8526
8527                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8528                                 biggest_datasize));
8529                 }
8530
8531                 /* the value is an UNICODE string but real_value_size is the length
8532                    in bytes including the trailing 0 */
8533
8534                 *out_value_len = 2 * (1+biggest_valuesize);
8535                 *out_data_len  = biggest_datasize;
8536
8537                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8538
8539                 goto done;
8540         }
8541
8542         /*
8543          * the value len is wrong in NT sp3
8544          * that's the number of bytes not the number of unicode chars
8545          */
8546
8547         if ( key_index != -1 )
8548                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8549
8550         if ( !val )
8551         {
8552
8553                 /* out_value should default to "" or else NT4 has
8554                    problems unmarshalling the response */
8555
8556                 *out_max_value_len=(in_value_len/sizeof(uint16));
8557
8558                 if (in_value_len) {
8559                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8560                         {
8561                                 result = WERR_NOMEM;
8562                                 goto done;
8563                         }
8564                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8565                 } else {
8566                         *out_value=NULL;
8567                         *out_value_len = 0;
8568                 }
8569
8570                 /* the data is counted in bytes */
8571
8572                 *out_max_data_len = in_data_len;
8573                 *out_data_len     = in_data_len;
8574
8575                 /* only allocate when given a non-zero data_len */
8576
8577                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8578                 {
8579                         result = WERR_NOMEM;
8580                         goto done;
8581                 }
8582
8583                 result = WERR_NO_MORE_ITEMS;
8584         }
8585         else
8586         {
8587                 /*
8588                  * the value is:
8589                  * - counted in bytes in the request
8590                  * - counted in UNICODE chars in the max reply
8591                  * - counted in bytes in the real size
8592                  *
8593                  * take a pause *before* coding not *during* coding
8594                  */
8595
8596                 /* name */
8597                 *out_max_value_len=(in_value_len/sizeof(uint16));
8598                 if (in_value_len) {
8599                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8600                         {
8601                                 result = WERR_NOMEM;
8602                                 goto done;
8603                         }
8604
8605                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8606                 } else {
8607                         *out_value = NULL;
8608                         *out_value_len = 0;
8609                 }
8610
8611                 /* type */
8612
8613                 *out_type = regval_type( val );
8614
8615                 /* data - counted in bytes */
8616
8617                 *out_max_data_len = in_data_len;
8618                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8619                 {
8620                         result = WERR_NOMEM;
8621                         goto done;
8622                 }
8623                 data_len = regval_size(val);
8624                 if ( *data_out && data_len )
8625                         memcpy( *data_out, regval_data_p(val), data_len );
8626                 *out_data_len = data_len;
8627         }
8628
8629 done:
8630         free_a_printer(&printer, 2);
8631         return result;
8632 }
8633
8634 /****************************************************************************
8635 ****************************************************************************/
8636
8637 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8638 {
8639         POLICY_HND              *handle = &q_u->handle;
8640         UNISTR2                 *value = &q_u->value;
8641         uint32                  type = q_u->type;
8642         uint8                   *data = q_u->data;
8643         uint32                  real_len = q_u->real_len;
8644
8645         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8646         int                     snum=0;
8647         WERROR                  status = WERR_OK;
8648         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8649         fstring                 valuename;
8650
8651         DEBUG(5,("spoolss_setprinterdata\n"));
8652
8653         if (!Printer) {
8654                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8655                 return WERR_BADFID;
8656         }
8657
8658         if ( Printer->printer_type == SPLHND_SERVER ) {
8659                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8660                 return WERR_INVALID_PARAM;
8661         }
8662
8663         if (!get_printer_snum(p,handle, &snum, NULL))
8664                 return WERR_BADFID;
8665
8666         /*
8667          * Access check : NT returns "access denied" if you make a
8668          * SetPrinterData call without the necessary privildge.
8669          * we were originally returning OK if nothing changed
8670          * which made Win2k issue **a lot** of SetPrinterData
8671          * when connecting to a printer  --jerry
8672          */
8673
8674         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8675         {
8676                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8677                 status = WERR_ACCESS_DENIED;
8678                 goto done;
8679         }
8680
8681         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8682         if (!W_ERROR_IS_OK(status))
8683                 return status;
8684
8685         unistr2_to_ascii(valuename, value, sizeof(valuename));
8686
8687         /*
8688          * When client side code sets a magic printer data key, detect it and save
8689          * the current printer data and the magic key's data (its the DEVMODE) for
8690          * future printer/driver initializations.
8691          */
8692         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8693         {
8694                 /* Set devmode and printer initialization info */
8695                 status = save_driver_init( printer, 2, data, real_len );
8696
8697                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8698         }
8699         else
8700         {
8701         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8702                                         type, data, real_len );
8703                 if ( W_ERROR_IS_OK(status) )
8704                         status = mod_a_printer(printer, 2);
8705         }
8706
8707 done:
8708         free_a_printer(&printer, 2);
8709
8710         return status;
8711 }
8712
8713 /****************************************************************
8714  _spoolss_ResetPrinter
8715 ****************************************************************/
8716
8717 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8718                              struct spoolss_ResetPrinter *r)
8719 {
8720         POLICY_HND      *handle = r->in.handle;
8721         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8722         int             snum;
8723
8724         DEBUG(5,("_spoolss_ResetPrinter\n"));
8725
8726         /*
8727          * All we do is to check to see if the handle and queue is valid.
8728          * This call really doesn't mean anything to us because we only
8729          * support RAW printing.   --jerry
8730          */
8731
8732         if (!Printer) {
8733                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8734                         OUR_HANDLE(handle)));
8735                 return WERR_BADFID;
8736         }
8737
8738         if (!get_printer_snum(p,handle, &snum, NULL))
8739                 return WERR_BADFID;
8740
8741
8742         /* blindly return success */
8743         return WERR_OK;
8744 }
8745
8746 /****************************************************************
8747  _spoolss_DeletePrinterData
8748 ****************************************************************/
8749
8750 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8751                                   struct spoolss_DeletePrinterData *r)
8752 {
8753         POLICY_HND      *handle = r->in.handle;
8754         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8755         int             snum=0;
8756         WERROR          status = WERR_OK;
8757         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8758
8759         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8760
8761         if (!Printer) {
8762                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8763                         OUR_HANDLE(handle)));
8764                 return WERR_BADFID;
8765         }
8766
8767         if (!get_printer_snum(p, handle, &snum, NULL))
8768                 return WERR_BADFID;
8769
8770         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8771                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8772                         "printer properties change denied by handle\n"));
8773                 return WERR_ACCESS_DENIED;
8774         }
8775
8776         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8777         if (!W_ERROR_IS_OK(status))
8778                 return status;
8779
8780         if (!r->in.value_name) {
8781                 free_a_printer(&printer, 2);
8782                 return WERR_NOMEM;
8783         }
8784
8785         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8786                                         r->in.value_name );
8787
8788         if ( W_ERROR_IS_OK(status) )
8789                 mod_a_printer( printer, 2 );
8790
8791         free_a_printer(&printer, 2);
8792
8793         return status;
8794 }
8795
8796 /****************************************************************
8797  _spoolss_AddForm
8798 ****************************************************************/
8799
8800 WERROR _spoolss_AddForm(pipes_struct *p,
8801                         struct spoolss_AddForm *r)
8802 {
8803         POLICY_HND *handle = r->in.handle;
8804         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8805         nt_forms_struct tmpForm;
8806         int snum;
8807         WERROR status = WERR_OK;
8808         NT_PRINTER_INFO_LEVEL *printer = NULL;
8809
8810         int count=0;
8811         nt_forms_struct *list=NULL;
8812         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8813
8814         DEBUG(5,("_spoolss_AddForm\n"));
8815
8816         if (!Printer) {
8817                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8818                         OUR_HANDLE(handle)));
8819                 return WERR_BADFID;
8820         }
8821
8822
8823         /* forms can be added on printer of on the print server handle */
8824
8825         if ( Printer->printer_type == SPLHND_PRINTER )
8826         {
8827                 if (!get_printer_snum(p,handle, &snum, NULL))
8828                         return WERR_BADFID;
8829
8830                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8831                 if (!W_ERROR_IS_OK(status))
8832                         goto done;
8833         }
8834
8835         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8836                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8837                 status = WERR_ACCESS_DENIED;
8838                 goto done;
8839         }
8840
8841         /* can't add if builtin */
8842
8843         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8844                 status = WERR_FILE_EXISTS;
8845                 goto done;
8846         }
8847
8848         count = get_ntforms(&list);
8849
8850         if(!add_a_form(&list, form, &count)) {
8851                 status =  WERR_NOMEM;
8852                 goto done;
8853         }
8854
8855         write_ntforms(&list, count);
8856
8857         /*
8858          * ChangeID must always be set if this is a printer
8859          */
8860
8861         if ( Printer->printer_type == SPLHND_PRINTER )
8862                 status = mod_a_printer(printer, 2);
8863
8864 done:
8865         if ( printer )
8866                 free_a_printer(&printer, 2);
8867         SAFE_FREE(list);
8868
8869         return status;
8870 }
8871
8872 /****************************************************************
8873  _spoolss_DeleteForm
8874 ****************************************************************/
8875
8876 WERROR _spoolss_DeleteForm(pipes_struct *p,
8877                            struct spoolss_DeleteForm *r)
8878 {
8879         POLICY_HND *handle = r->in.handle;
8880         const char *form_name = r->in.form_name;
8881         nt_forms_struct tmpForm;
8882         int count=0;
8883         nt_forms_struct *list=NULL;
8884         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8885         int snum;
8886         WERROR status = WERR_OK;
8887         NT_PRINTER_INFO_LEVEL *printer = NULL;
8888
8889         DEBUG(5,("_spoolss_DeleteForm\n"));
8890
8891         if (!Printer) {
8892                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8893                         OUR_HANDLE(handle)));
8894                 return WERR_BADFID;
8895         }
8896
8897         /* forms can be deleted on printer of on the print server handle */
8898
8899         if ( Printer->printer_type == SPLHND_PRINTER )
8900         {
8901                 if (!get_printer_snum(p,handle, &snum, NULL))
8902                         return WERR_BADFID;
8903
8904                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8905                 if (!W_ERROR_IS_OK(status))
8906                         goto done;
8907         }
8908
8909         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8910                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8911                 status = WERR_ACCESS_DENIED;
8912                 goto done;
8913         }
8914
8915         /* can't delete if builtin */
8916
8917         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8918                 status = WERR_INVALID_PARAM;
8919                 goto done;
8920         }
8921
8922         count = get_ntforms(&list);
8923
8924         if ( !delete_a_form(&list, form_name, &count, &status ))
8925                 goto done;
8926
8927         /*
8928          * ChangeID must always be set if this is a printer
8929          */
8930
8931         if ( Printer->printer_type == SPLHND_PRINTER )
8932                 status = mod_a_printer(printer, 2);
8933
8934 done:
8935         if ( printer )
8936                 free_a_printer(&printer, 2);
8937         SAFE_FREE(list);
8938
8939         return status;
8940 }
8941
8942 /****************************************************************
8943  _spoolss_SetForm
8944 ****************************************************************/
8945
8946 WERROR _spoolss_SetForm(pipes_struct *p,
8947                         struct spoolss_SetForm *r)
8948 {
8949         POLICY_HND *handle = r->in.handle;
8950         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8951         nt_forms_struct tmpForm;
8952         int snum;
8953         WERROR status = WERR_OK;
8954         NT_PRINTER_INFO_LEVEL *printer = NULL;
8955
8956         int count=0;
8957         nt_forms_struct *list=NULL;
8958         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8959
8960         DEBUG(5,("_spoolss_SetForm\n"));
8961
8962         if (!Printer) {
8963                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8964                         OUR_HANDLE(handle)));
8965                 return WERR_BADFID;
8966         }
8967
8968         /* forms can be modified on printer of on the print server handle */
8969
8970         if ( Printer->printer_type == SPLHND_PRINTER )
8971         {
8972                 if (!get_printer_snum(p,handle, &snum, NULL))
8973                         return WERR_BADFID;
8974
8975                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8976                 if (!W_ERROR_IS_OK(status))
8977                         goto done;
8978         }
8979
8980         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8981                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8982                 status = WERR_ACCESS_DENIED;
8983                 goto done;
8984         }
8985
8986         /* can't set if builtin */
8987         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8988                 status = WERR_INVALID_PARAM;
8989                 goto done;
8990         }
8991
8992         count = get_ntforms(&list);
8993         update_a_form(&list, form, count);
8994         write_ntforms(&list, count);
8995
8996         /*
8997          * ChangeID must always be set if this is a printer
8998          */
8999
9000         if ( Printer->printer_type == SPLHND_PRINTER )
9001                 status = mod_a_printer(printer, 2);
9002
9003
9004 done:
9005         if ( printer )
9006                 free_a_printer(&printer, 2);
9007         SAFE_FREE(list);
9008
9009         return status;
9010 }
9011
9012 /****************************************************************************
9013  fill_print_processor1
9014 ****************************************************************************/
9015
9016 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9017                                     struct spoolss_PrintProcessorInfo1 *r,
9018                                     const char *print_processor_name)
9019 {
9020         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9021         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9022
9023         return WERR_OK;
9024 }
9025
9026 /****************************************************************************
9027  enumprintprocessors level 1.
9028 ****************************************************************************/
9029
9030 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9031                                           union spoolss_PrintProcessorInfo **info_p,
9032                                           uint32_t *count)
9033 {
9034         union spoolss_PrintProcessorInfo *info;
9035         WERROR result;
9036
9037         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9038         W_ERROR_HAVE_NO_MEMORY(info);
9039
9040         *count = 1;
9041
9042         result = fill_print_processor1(info, &info[0].info1, "winprint");
9043         if (!W_ERROR_IS_OK(result)) {
9044                 goto out;
9045         }
9046
9047  out:
9048         if (!W_ERROR_IS_OK(result)) {
9049                 TALLOC_FREE(info);
9050                 *count = 0;
9051                 return result;
9052         }
9053
9054         *info_p = info;
9055
9056         return WERR_OK;
9057 }
9058
9059 /****************************************************************
9060  _spoolss_EnumPrintProcessors
9061 ****************************************************************/
9062
9063 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
9064                                     struct spoolss_EnumPrintProcessors *r)
9065 {
9066         WERROR result;
9067
9068         /* that's an [in out] buffer */
9069
9070         if (!r->in.buffer && (r->in.offered != 0)) {
9071                 return WERR_INVALID_PARAM;
9072         }
9073
9074         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9075
9076         /*
9077          * Enumerate the print processors ...
9078          *
9079          * Just reply with "winprint", to keep NT happy
9080          * and I can use my nice printer checker.
9081          */
9082
9083         *r->out.count = 0;
9084         *r->out.needed = 0;
9085         *r->out.info = NULL;
9086
9087         switch (r->in.level) {
9088         case 1:
9089                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9090                                                      r->out.count);
9091                 break;
9092         default:
9093                 return WERR_UNKNOWN_LEVEL;
9094         }
9095
9096         if (!W_ERROR_IS_OK(result)) {
9097                 return result;
9098         }
9099
9100         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9101                                                      spoolss_EnumPrintProcessors, NULL,
9102                                                      *r->out.info, r->in.level,
9103                                                      *r->out.count);
9104         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9105         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9106
9107         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9108 }
9109
9110 /****************************************************************************
9111  fill_printprocdatatype1
9112 ****************************************************************************/
9113
9114 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9115                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9116                                       const char *name_array)
9117 {
9118         r->name_array = talloc_strdup(mem_ctx, name_array);
9119         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9120
9121         return WERR_OK;
9122 }
9123
9124 /****************************************************************************
9125  enumprintprocdatatypes level 1.
9126 ****************************************************************************/
9127
9128 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9129                                              union spoolss_PrintProcDataTypesInfo **info_p,
9130                                              uint32_t *count)
9131 {
9132         WERROR result;
9133         union spoolss_PrintProcDataTypesInfo *info;
9134
9135         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9136         W_ERROR_HAVE_NO_MEMORY(info);
9137
9138         *count = 1;
9139
9140         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9141         if (!W_ERROR_IS_OK(result)) {
9142                 goto out;
9143         }
9144
9145  out:
9146         if (!W_ERROR_IS_OK(result)) {
9147                 TALLOC_FREE(info);
9148                 *count = 0;
9149                 return result;
9150         }
9151
9152         *info_p = info;
9153
9154         return WERR_OK;
9155 }
9156
9157 /****************************************************************
9158  _spoolss_EnumPrintProcDataTypes
9159 ****************************************************************/
9160
9161 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
9162                                        struct spoolss_EnumPrintProcDataTypes *r)
9163 {
9164         WERROR result;
9165
9166         /* that's an [in out] buffer */
9167
9168         if (!r->in.buffer && (r->in.offered != 0)) {
9169                 return WERR_INVALID_PARAM;
9170         }
9171
9172         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9173
9174         *r->out.count = 0;
9175         *r->out.needed = 0;
9176         *r->out.info = NULL;
9177
9178         switch (r->in.level) {
9179         case 1:
9180                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9181                                                         r->out.count);
9182                 break;
9183         default:
9184                 return WERR_UNKNOWN_LEVEL;
9185         }
9186
9187         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9188                                                      spoolss_EnumPrintProcDataTypes, NULL,
9189                                                      *r->out.info, r->in.level,
9190                                                      *r->out.count);
9191         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9192         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9193
9194         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9195 }
9196
9197 /****************************************************************************
9198  fill_monitor_1
9199 ****************************************************************************/
9200
9201 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9202                              struct spoolss_MonitorInfo1 *r,
9203                              const char *monitor_name)
9204 {
9205         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9206         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9207
9208         return WERR_OK;
9209 }
9210
9211 /****************************************************************************
9212  fill_monitor_2
9213 ****************************************************************************/
9214
9215 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9216                              struct spoolss_MonitorInfo2 *r,
9217                              const char *monitor_name,
9218                              const char *environment,
9219                              const char *dll_name)
9220 {
9221         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9222         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9223         r->environment                  = talloc_strdup(mem_ctx, environment);
9224         W_ERROR_HAVE_NO_MEMORY(r->environment);
9225         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9226         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9227
9228         return WERR_OK;
9229 }
9230
9231 /****************************************************************************
9232  enumprintmonitors level 1.
9233 ****************************************************************************/
9234
9235 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9236                                         union spoolss_MonitorInfo **info_p,
9237                                         uint32_t *count)
9238 {
9239         union spoolss_MonitorInfo *info;
9240         WERROR result = WERR_OK;
9241
9242         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9243         W_ERROR_HAVE_NO_MEMORY(info);
9244
9245         *count = 2;
9246
9247         result = fill_monitor_1(info, &info[0].info1,
9248                                 SPL_LOCAL_PORT /* FIXME */);
9249         if (!W_ERROR_IS_OK(result)) {
9250                 goto out;
9251         }
9252
9253         result = fill_monitor_1(info, &info[1].info1,
9254                                 SPL_TCPIP_PORT /* FIXME */);
9255         if (!W_ERROR_IS_OK(result)) {
9256                 goto out;
9257         }
9258
9259 out:
9260         if (!W_ERROR_IS_OK(result)) {
9261                 TALLOC_FREE(info);
9262                 *count = 0;
9263                 return result;
9264         }
9265
9266         *info_p = info;
9267
9268         return WERR_OK;
9269 }
9270
9271 /****************************************************************************
9272  enumprintmonitors level 2.
9273 ****************************************************************************/
9274
9275 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9276                                         union spoolss_MonitorInfo **info_p,
9277                                         uint32_t *count)
9278 {
9279         union spoolss_MonitorInfo *info;
9280         WERROR result = WERR_OK;
9281
9282         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9283         W_ERROR_HAVE_NO_MEMORY(info);
9284
9285         *count = 2;
9286
9287         result = fill_monitor_2(info, &info[0].info2,
9288                                 SPL_LOCAL_PORT, /* FIXME */
9289                                 "Windows NT X86", /* FIXME */
9290                                 "localmon.dll");
9291         if (!W_ERROR_IS_OK(result)) {
9292                 goto out;
9293         }
9294
9295         result = fill_monitor_2(info, &info[1].info2,
9296                                 SPL_TCPIP_PORT, /* FIXME */
9297                                 "Windows NT X86", /* FIXME */
9298                                 "tcpmon.dll");
9299         if (!W_ERROR_IS_OK(result)) {
9300                 goto out;
9301         }
9302
9303 out:
9304         if (!W_ERROR_IS_OK(result)) {
9305                 TALLOC_FREE(info);
9306                 *count = 0;
9307                 return result;
9308         }
9309
9310         *info_p = info;
9311
9312         return WERR_OK;
9313 }
9314
9315 /****************************************************************
9316  _spoolss_EnumMonitors
9317 ****************************************************************/
9318
9319 WERROR _spoolss_EnumMonitors(pipes_struct *p,
9320                              struct spoolss_EnumMonitors *r)
9321 {
9322         WERROR result;
9323
9324         /* that's an [in out] buffer */
9325
9326         if (!r->in.buffer && (r->in.offered != 0)) {
9327                 return WERR_INVALID_PARAM;
9328         }
9329
9330         DEBUG(5,("_spoolss_EnumMonitors\n"));
9331
9332         /*
9333          * Enumerate the print monitors ...
9334          *
9335          * Just reply with "Local Port", to keep NT happy
9336          * and I can use my nice printer checker.
9337          */
9338
9339         *r->out.count = 0;
9340         *r->out.needed = 0;
9341         *r->out.info = NULL;
9342
9343         switch (r->in.level) {
9344         case 1:
9345                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9346                                                    r->out.count);
9347                 break;
9348         case 2:
9349                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9350                                                    r->out.count);
9351                 break;
9352         default:
9353                 return WERR_UNKNOWN_LEVEL;
9354         }
9355
9356         if (!W_ERROR_IS_OK(result)) {
9357                 return result;
9358         }
9359
9360         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9361                                                      spoolss_EnumMonitors, NULL,
9362                                                      *r->out.info, r->in.level,
9363                                                      *r->out.count);
9364         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9365         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9366
9367         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9368 }
9369
9370 /****************************************************************************
9371 ****************************************************************************/
9372
9373 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9374                              const print_queue_struct *queue,
9375                              int count, int snum,
9376                              const NT_PRINTER_INFO_LEVEL *ntprinter,
9377                              uint32_t jobid,
9378                              struct spoolss_JobInfo1 *r)
9379 {
9380         int i = 0;
9381         bool found = false;
9382
9383         for (i=0; i<count && found == false; i++) {
9384                 if (queue[i].job == (int)jobid) {
9385                         found = true;
9386                 }
9387         }
9388
9389         if (found == false) {
9390                 /* NT treats not found as bad param... yet another bad choice */
9391                 return WERR_INVALID_PARAM;
9392         }
9393
9394         return fill_job_info1(mem_ctx,
9395                               r,
9396                               &queue[i-1],
9397                               i,
9398                               snum,
9399                               ntprinter);
9400 }
9401
9402 /****************************************************************************
9403 ****************************************************************************/
9404
9405 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9406                              const print_queue_struct *queue,
9407                              int count, int snum,
9408                              const NT_PRINTER_INFO_LEVEL *ntprinter,
9409                              uint32_t jobid,
9410                              struct spoolss_JobInfo2 *r)
9411 {
9412         int i = 0;
9413         bool found = false;
9414         struct spoolss_DeviceMode *devmode;
9415         NT_DEVICEMODE *nt_devmode;
9416         WERROR result;
9417
9418         for (i=0; i<count && found == false; i++) {
9419                 if (queue[i].job == (int)jobid) {
9420                         found = true;
9421                 }
9422         }
9423
9424         if (found == false) {
9425                 /* NT treats not found as bad param... yet another bad
9426                    choice */
9427                 return WERR_INVALID_PARAM;
9428         }
9429
9430         /*
9431          * if the print job does not have a DEVMODE associated with it,
9432          * just use the one for the printer. A NULL devicemode is not
9433          *  a failure condition
9434          */
9435
9436         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9437         if (nt_devmode) {
9438                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
9439                 W_ERROR_HAVE_NO_MEMORY(devmode);
9440                 result = convert_nt_devicemode_new(devmode, devmode, nt_devmode);
9441                 if (!W_ERROR_IS_OK(result)) {
9442                         return result;
9443                 }
9444         } else {
9445                 devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
9446                 W_ERROR_HAVE_NO_MEMORY(devmode);
9447         }
9448
9449         return fill_job_info2(mem_ctx,
9450                               r,
9451                               &queue[i-1],
9452                               i,
9453                               snum,
9454                               ntprinter,
9455                               devmode);
9456 }
9457
9458 /****************************************************************
9459  _spoolss_GetJob
9460 ****************************************************************/
9461
9462 WERROR _spoolss_GetJob(pipes_struct *p,
9463                        struct spoolss_GetJob *r)
9464 {
9465         WERROR result = WERR_OK;
9466         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9467         int snum;
9468         int count;
9469         print_queue_struct      *queue = NULL;
9470         print_status_struct prt_status;
9471
9472         /* that's an [in out] buffer */
9473
9474         if (!r->in.buffer && (r->in.offered != 0)) {
9475                 return WERR_INVALID_PARAM;
9476         }
9477
9478         DEBUG(5,("_spoolss_GetJob\n"));
9479
9480         *r->out.needed = 0;
9481
9482         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9483                 return WERR_BADFID;
9484         }
9485
9486         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9487         if (!W_ERROR_IS_OK(result)) {
9488                 return result;
9489         }
9490
9491         count = print_queue_status(snum, &queue, &prt_status);
9492
9493         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9494                      count, prt_status.status, prt_status.message));
9495
9496         switch (r->in.level) {
9497         case 1:
9498                 result = getjob_level_1(p->mem_ctx,
9499                                         queue, count, snum, ntprinter,
9500                                         r->in.job_id, &r->out.info->info1);
9501                 break;
9502         case 2:
9503                 result = getjob_level_2(p->mem_ctx,
9504                                         queue, count, snum, ntprinter,
9505                                         r->in.job_id, &r->out.info->info2);
9506                 break;
9507         default:
9508                 result = WERR_UNKNOWN_LEVEL;
9509                 break;
9510         }
9511
9512         SAFE_FREE(queue);
9513         free_a_printer(&ntprinter, 2);
9514
9515         if (!W_ERROR_IS_OK(result)) {
9516                 TALLOC_FREE(r->out.info);
9517                 return result;
9518         }
9519
9520         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9521                                                r->out.info, r->in.level);
9522         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9523
9524         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9525 }
9526
9527 /****************************************************************
9528  _spoolss_GetPrinterDataEx
9529
9530  From MSDN documentation of GetPrinterDataEx: pass request
9531  to GetPrinterData if key is "PrinterDriverData".
9532 ****************************************************************/
9533
9534 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9535                                  struct spoolss_GetPrinterDataEx *r)
9536 {
9537         POLICY_HND      *handle = r->in.handle;
9538         uint8           *data = NULL;
9539         const char      *keyname = r->in.key_name;
9540         const char      *valuename = r->in.value_name;
9541
9542         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9543
9544         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9545         int                     snum = 0;
9546         WERROR                  status = WERR_OK;
9547
9548         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9549
9550         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9551                 keyname, valuename));
9552
9553         /* in case of problem, return some default values */
9554
9555         *r->out.needed  = 0;
9556         *r->out.type    = 0;
9557
9558         if (!Printer) {
9559                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9560                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9561                 status = WERR_BADFID;
9562                 goto done;
9563         }
9564
9565         /* Is the handle to a printer or to the server? */
9566
9567         if (Printer->printer_type == SPLHND_SERVER) {
9568                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9569                         "Not implemented for server handles yet\n"));
9570                 status = WERR_INVALID_PARAM;
9571                 goto done;
9572         }
9573
9574         if ( !get_printer_snum(p,handle, &snum, NULL) )
9575                 return WERR_BADFID;
9576
9577         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9578         if ( !W_ERROR_IS_OK(status) )
9579                 goto done;
9580
9581         /* check to see if the keyname is valid */
9582         if ( !strlen(keyname) ) {
9583                 status = WERR_INVALID_PARAM;
9584                 goto done;
9585         }
9586
9587         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9588                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9589                         "Invalid keyname [%s]\n", keyname ));
9590                 free_a_printer( &printer, 2 );
9591                 status = WERR_BADFILE;
9592                 goto done;
9593         }
9594
9595         /* When given a new keyname, we should just create it */
9596
9597         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9598                                      r->out.type, &data, r->out.needed,
9599                                      r->in.offered );
9600
9601         if (*r->out.needed > r->in.offered) {
9602                 status = WERR_MORE_DATA;
9603         }
9604
9605         if (W_ERROR_IS_OK(status)) {
9606                 memcpy(r->out.buffer, data, r->in.offered);
9607         }
9608
9609 done:
9610         if ( printer )
9611         free_a_printer( &printer, 2 );
9612
9613         return status;
9614 }
9615
9616 /****************************************************************
9617  _spoolss_SetPrinterDataEx
9618 ****************************************************************/
9619
9620 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9621                                  struct spoolss_SetPrinterDataEx *r)
9622 {
9623         POLICY_HND              *handle = r->in.handle;
9624         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9625         int                     snum = 0;
9626         WERROR                  status = WERR_OK;
9627         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9628         char                    *oid_string;
9629
9630         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9631
9632         /* From MSDN documentation of SetPrinterDataEx: pass request to
9633            SetPrinterData if key is "PrinterDriverData" */
9634
9635         if (!Printer) {
9636                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9637                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9638                 return WERR_BADFID;
9639         }
9640
9641         if ( Printer->printer_type == SPLHND_SERVER ) {
9642                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9643                         "Not implemented for server handles yet\n"));
9644                 return WERR_INVALID_PARAM;
9645         }
9646
9647         if ( !get_printer_snum(p,handle, &snum, NULL) )
9648                 return WERR_BADFID;
9649
9650         /*
9651          * Access check : NT returns "access denied" if you make a
9652          * SetPrinterData call without the necessary privildge.
9653          * we were originally returning OK if nothing changed
9654          * which made Win2k issue **a lot** of SetPrinterData
9655          * when connecting to a printer  --jerry
9656          */
9657
9658         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9659         {
9660                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9661                         "change denied by handle access permissions\n"));
9662                 return WERR_ACCESS_DENIED;
9663         }
9664
9665         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9666         if (!W_ERROR_IS_OK(status))
9667                 return status;
9668
9669         /* check for OID in valuename */
9670
9671         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9672         {
9673                 *oid_string = '\0';
9674                 oid_string++;
9675         }
9676
9677         /* save the registry data */
9678
9679         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9680                                      r->in.type, r->in.buffer, r->in.offered );
9681
9682         if ( W_ERROR_IS_OK(status) )
9683         {
9684                 /* save the OID if one was specified */
9685                 if ( oid_string ) {
9686                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9687                                 r->in.key_name, SPOOL_OID_KEY);
9688                         if (!str) {
9689                                 return WERR_NOMEM;
9690                         }
9691
9692                         /*
9693                          * I'm not checking the status here on purpose.  Don't know
9694                          * if this is right, but I'm returning the status from the
9695                          * previous set_printer_dataex() call.  I have no idea if
9696                          * this is right.    --jerry
9697                          */
9698
9699                         set_printer_dataex( printer, str, r->in.value_name,
9700                                             REG_SZ, (uint8 *)oid_string,
9701                                             strlen(oid_string)+1 );
9702                 }
9703
9704                 status = mod_a_printer(printer, 2);
9705         }
9706
9707         free_a_printer(&printer, 2);
9708
9709         return status;
9710 }
9711
9712 /****************************************************************
9713  _spoolss_DeletePrinterDataEx
9714 ****************************************************************/
9715
9716 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9717                                     struct spoolss_DeletePrinterDataEx *r)
9718 {
9719         POLICY_HND      *handle = r->in.handle;
9720         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9721         int             snum=0;
9722         WERROR          status = WERR_OK;
9723         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9724
9725         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9726
9727         if (!Printer) {
9728                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9729                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9730                 return WERR_BADFID;
9731         }
9732
9733         if (!get_printer_snum(p, handle, &snum, NULL))
9734                 return WERR_BADFID;
9735
9736         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9737                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9738                         "printer properties change denied by handle\n"));
9739                 return WERR_ACCESS_DENIED;
9740         }
9741
9742         if (!r->in.value_name || !r->in.key_name) {
9743                 return WERR_NOMEM;
9744         }
9745
9746         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9747         if (!W_ERROR_IS_OK(status))
9748                 return status;
9749
9750         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9751
9752         if ( W_ERROR_IS_OK(status) )
9753                 mod_a_printer( printer, 2 );
9754
9755         free_a_printer(&printer, 2);
9756
9757         return status;
9758 }
9759
9760 /********************************************************************
9761  * spoolss_enumprinterkey
9762  ********************************************************************/
9763
9764
9765 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9766 {
9767         fstring         key;
9768         fstring         *keynames = NULL;
9769         uint16          *enumkeys = NULL;
9770         int             num_keys;
9771         int             printerkey_len;
9772         POLICY_HND      *handle = &q_u->handle;
9773         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9774         NT_PRINTER_DATA *data;
9775         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9776         int             snum = 0;
9777         WERROR          status = WERR_BADFILE;
9778
9779
9780         DEBUG(4,("_spoolss_enumprinterkey\n"));
9781
9782         if (!Printer) {
9783                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9784                 return WERR_BADFID;
9785         }
9786
9787         if ( !get_printer_snum(p,handle, &snum, NULL) )
9788                 return WERR_BADFID;
9789
9790         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9791         if (!W_ERROR_IS_OK(status))
9792                 return status;
9793
9794         /* get the list of subkey names */
9795
9796         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9797         data = printer->info_2->data;
9798
9799         num_keys = get_printer_subkeys( data, key, &keynames );
9800
9801         if ( num_keys == -1 ) {
9802                 status = WERR_BADFILE;
9803                 goto done;
9804         }
9805
9806         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9807
9808         r_u->needed = printerkey_len*2;
9809
9810         if ( q_u->size < r_u->needed ) {
9811                 status = WERR_MORE_DATA;
9812                 goto done;
9813         }
9814
9815         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9816                 status = WERR_NOMEM;
9817                 goto done;
9818         }
9819
9820         status = WERR_OK;
9821
9822         if ( q_u->size < r_u->needed )
9823                 status = WERR_MORE_DATA;
9824
9825 done:
9826         free_a_printer( &printer, 2 );
9827         SAFE_FREE( keynames );
9828
9829         return status;
9830 }
9831
9832 /****************************************************************
9833  _spoolss_DeletePrinterKey
9834 ****************************************************************/
9835
9836 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9837                                  struct spoolss_DeletePrinterKey *r)
9838 {
9839         POLICY_HND              *handle = r->in.handle;
9840         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9841         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9842         int                     snum=0;
9843         WERROR                  status;
9844
9845         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9846
9847         if (!Printer) {
9848                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9849                         OUR_HANDLE(handle)));
9850                 return WERR_BADFID;
9851         }
9852
9853         /* if keyname == NULL, return error */
9854
9855         if ( !r->in.key_name )
9856                 return WERR_INVALID_PARAM;
9857
9858         if (!get_printer_snum(p, handle, &snum, NULL))
9859                 return WERR_BADFID;
9860
9861         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9862                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9863                         "printer properties change denied by handle\n"));
9864                 return WERR_ACCESS_DENIED;
9865         }
9866
9867         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9868         if (!W_ERROR_IS_OK(status))
9869                 return status;
9870
9871         /* delete the key and all subneys */
9872
9873         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9874
9875         if ( W_ERROR_IS_OK(status) )
9876                 status = mod_a_printer(printer, 2);
9877
9878         free_a_printer( &printer, 2 );
9879
9880         return status;
9881 }
9882
9883
9884 /********************************************************************
9885  * spoolss_enumprinterdataex
9886  ********************************************************************/
9887
9888 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9889 {
9890         POLICY_HND      *handle = &q_u->handle;
9891         uint32          in_size = q_u->size;
9892         uint32          num_entries,
9893                         needed;
9894         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9895         PRINTER_ENUM_VALUES     *enum_values = NULL;
9896         NT_PRINTER_DATA         *p_data;
9897         fstring         key;
9898         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9899         int             snum;
9900         WERROR          result;
9901         int             key_index;
9902         int             i;
9903         REGISTRY_VALUE  *val;
9904         char            *value_name;
9905         uint32          data_len;
9906
9907
9908         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9909
9910         if (!Printer) {
9911                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9912                 return WERR_BADFID;
9913         }
9914
9915         /*
9916          * first check for a keyname of NULL or "".  Win2k seems to send
9917          * this a lot and we should send back WERR_INVALID_PARAM
9918          * no need to spend time looking up the printer in this case.
9919          * --jerry
9920          */
9921
9922         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9923         if ( !strlen(key) ) {
9924                 result = WERR_INVALID_PARAM;
9925                 goto done;
9926         }
9927
9928         /* get the printer off of disk */
9929
9930         if (!get_printer_snum(p,handle, &snum, NULL))
9931                 return WERR_BADFID;
9932
9933         ZERO_STRUCT(printer);
9934         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9935         if (!W_ERROR_IS_OK(result))
9936                 return result;
9937
9938         /* now look for a match on the key name */
9939
9940         p_data = printer->info_2->data;
9941
9942         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9943         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9944         {
9945                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9946                 result = WERR_INVALID_PARAM;
9947                 goto done;
9948         }
9949
9950         result = WERR_OK;
9951         needed = 0;
9952
9953         /* allocate the memory for the array of pointers -- if necessary */
9954
9955         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9956         if ( num_entries )
9957         {
9958                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9959                 {
9960                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9961                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9962                         result = WERR_NOMEM;
9963                         goto done;
9964                 }
9965
9966                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9967         }
9968
9969         /*
9970          * loop through all params and build the array to pass
9971          * back to the  client
9972          */
9973
9974         for ( i=0; i<num_entries; i++ )
9975         {
9976                 /* lookup the registry value */
9977
9978                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9979                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9980
9981                 /* copy the data */
9982
9983                 value_name = regval_name( val );
9984                 init_unistr( &enum_values[i].valuename, value_name );
9985                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9986                 enum_values[i].type      = regval_type( val );
9987
9988                 data_len = regval_size( val );
9989                 if ( data_len ) {
9990                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9991                         {
9992                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9993                                         data_len ));
9994                                 result = WERR_NOMEM;
9995                                 goto done;
9996                         }
9997                 }
9998                 enum_values[i].data_len = data_len;
9999
10000                 /* keep track of the size of the array in bytes */
10001
10002                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
10003         }
10004
10005         /* housekeeping information in the reply */
10006
10007         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10008          * the hand marshalled container size is a multiple
10009          * of 4 bytes for RPC alignment.
10010          */
10011
10012         if (needed % 4) {
10013                 needed += 4-(needed % 4);
10014         }
10015
10016         r_u->needed     = needed;
10017         r_u->returned   = num_entries;
10018
10019         if (needed > in_size) {
10020                 result = WERR_MORE_DATA;
10021                 goto done;
10022         }
10023
10024         /* copy data into the reply */
10025
10026         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
10027            response buffer size is != the offered buffer size
10028
10029                 r_u->ctr.size           = r_u->needed;
10030         */
10031         r_u->ctr.size           = in_size;
10032
10033         r_u->ctr.size_of_array  = r_u->returned;
10034         r_u->ctr.values         = enum_values;
10035
10036 done:
10037         if ( printer )
10038         free_a_printer(&printer, 2);
10039
10040         return result;
10041 }
10042
10043 /****************************************************************************
10044 ****************************************************************************/
10045
10046 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10047                                                  const char *servername,
10048                                                  const char *environment,
10049                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10050 {
10051         WERROR werr;
10052         char *path = NULL;
10053
10054         werr = compose_spoolss_server_path(mem_ctx,
10055                                            servername,
10056                                            environment,
10057                                            SPOOLSS_PRTPROCS_PATH,
10058                                            &path);
10059         if (!W_ERROR_IS_OK(werr)) {
10060                 return werr;
10061         }
10062
10063         DEBUG(4,("print processor directory: [%s]\n", path));
10064
10065         r->directory_name = path;
10066
10067         return WERR_OK;
10068 }
10069
10070 /****************************************************************
10071  _spoolss_GetPrintProcessorDirectory
10072 ****************************************************************/
10073
10074 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10075                                            struct spoolss_GetPrintProcessorDirectory *r)
10076 {
10077         WERROR result;
10078
10079         /* that's an [in out] buffer */
10080
10081         if (!r->in.buffer && (r->in.offered != 0)) {
10082                 return WERR_INVALID_PARAM;
10083         }
10084
10085         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10086                 r->in.level));
10087
10088         *r->out.needed = 0;
10089
10090         /* r->in.level is ignored */
10091
10092         result = getprintprocessordirectory_level_1(p->mem_ctx,
10093                                                     r->in.server,
10094                                                     r->in.environment,
10095                                                     &r->out.info->info1);
10096         if (!W_ERROR_IS_OK(result)) {
10097                 TALLOC_FREE(r->out.info);
10098                 return result;
10099         }
10100
10101         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
10102                                                r->out.info, r->in.level);
10103         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10104
10105         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10106 }
10107
10108 /*******************************************************************
10109  ********************************************************************/
10110
10111 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10112                                const char *dllname)
10113 {
10114         enum ndr_err_code ndr_err;
10115         struct spoolss_MonitorUi ui;
10116
10117         ui.dll_name = dllname;
10118
10119         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
10120                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10121         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10122                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10123         }
10124         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10125 }
10126
10127 /*******************************************************************
10128  Streams the monitor UI DLL name in UNICODE
10129 *******************************************************************/
10130
10131 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10132                                NT_USER_TOKEN *token, DATA_BLOB *in,
10133                                DATA_BLOB *out, uint32_t *needed)
10134 {
10135         const char *dllname = "tcpmonui.dll";
10136
10137         *needed = (strlen(dllname)+1) * 2;
10138
10139         if (out->length < *needed) {
10140                 return WERR_INSUFFICIENT_BUFFER;
10141         }
10142
10143         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10144                 return WERR_NOMEM;
10145         }
10146
10147         return WERR_OK;
10148 }
10149
10150 /*******************************************************************
10151  ********************************************************************/
10152
10153 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10154                              struct spoolss_PortData1 *port1,
10155                              const DATA_BLOB *buf)
10156 {
10157         enum ndr_err_code ndr_err;
10158         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
10159                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10160         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10161                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10162         }
10163         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10164 }
10165
10166 /*******************************************************************
10167  ********************************************************************/
10168
10169 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10170                              struct spoolss_PortData2 *port2,
10171                              const DATA_BLOB *buf)
10172 {
10173         enum ndr_err_code ndr_err;
10174         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
10175                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10176         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10177                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10178         }
10179         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10180 }
10181
10182 /*******************************************************************
10183  Create a new TCP/IP port
10184 *******************************************************************/
10185
10186 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10187                              NT_USER_TOKEN *token, DATA_BLOB *in,
10188                              DATA_BLOB *out, uint32_t *needed)
10189 {
10190         struct spoolss_PortData1 port1;
10191         struct spoolss_PortData2 port2;
10192         char *device_uri = NULL;
10193         uint32_t version;
10194
10195         const char *portname;
10196         const char *hostaddress;
10197         const char *queue;
10198         uint32_t port_number;
10199         uint32_t protocol;
10200
10201         /* peek for spoolss_PortData version */
10202
10203         if (!in || (in->length < (128 + 4))) {
10204                 return WERR_GENERAL_FAILURE;
10205         }
10206
10207         version = IVAL(in->data, 128);
10208
10209         switch (version) {
10210                 case 1:
10211                         ZERO_STRUCT(port1);
10212
10213                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10214                                 return WERR_NOMEM;
10215                         }
10216
10217                         portname        = port1.portname;
10218                         hostaddress     = port1.hostaddress;
10219                         queue           = port1.queue;
10220                         protocol        = port1.protocol;
10221                         port_number     = port1.port_number;
10222
10223                         break;
10224                 case 2:
10225                         ZERO_STRUCT(port2);
10226
10227                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10228                                 return WERR_NOMEM;
10229                         }
10230
10231                         portname        = port2.portname;
10232                         hostaddress     = port2.hostaddress;
10233                         queue           = port2.queue;
10234                         protocol        = port2.protocol;
10235                         port_number     = port2.port_number;
10236
10237                         break;
10238                 default:
10239                         DEBUG(1,("xcvtcp_addport: "
10240                                 "unknown version of port_data: %d\n", version));
10241                         return WERR_UNKNOWN_PORT;
10242         }
10243
10244         /* create the device URI and call the add_port_hook() */
10245
10246         switch (protocol) {
10247         case PROTOCOL_RAWTCP_TYPE:
10248                 device_uri = talloc_asprintf(mem_ctx,
10249                                 "socket://%s:%d/", hostaddress,
10250                                 port_number);
10251                 break;
10252
10253         case PROTOCOL_LPR_TYPE:
10254                 device_uri = talloc_asprintf(mem_ctx,
10255                         "lpr://%s/%s", hostaddress, queue );
10256                 break;
10257
10258         default:
10259                 return WERR_UNKNOWN_PORT;
10260         }
10261
10262         if (!device_uri) {
10263                 return WERR_NOMEM;
10264         }
10265
10266         return add_port_hook(mem_ctx, token, portname, device_uri);
10267 }
10268
10269 /*******************************************************************
10270 *******************************************************************/
10271
10272 struct xcv_api_table xcvtcp_cmds[] = {
10273         { "MonitorUI",  xcvtcp_monitorui },
10274         { "AddPort",    xcvtcp_addport},
10275         { NULL,         NULL }
10276 };
10277
10278 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10279                                      NT_USER_TOKEN *token, const char *command,
10280                                      DATA_BLOB *inbuf,
10281                                      DATA_BLOB *outbuf,
10282                                      uint32_t *needed )
10283 {
10284         int i;
10285
10286         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10287
10288         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10289                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10290                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10291         }
10292
10293         return WERR_BADFUNC;
10294 }
10295
10296 /*******************************************************************
10297 *******************************************************************/
10298 #if 0   /* don't support management using the "Local Port" monitor */
10299
10300 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10301                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10302                                  DATA_BLOB *out, uint32_t *needed)
10303 {
10304         const char *dllname = "localui.dll";
10305
10306         *needed = (strlen(dllname)+1) * 2;
10307
10308         if (out->length < *needed) {
10309                 return WERR_INSUFFICIENT_BUFFER;
10310         }
10311
10312         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10313                 return WERR_NOMEM;
10314         }
10315
10316         return WERR_OK;
10317 }
10318
10319 /*******************************************************************
10320 *******************************************************************/
10321
10322 struct xcv_api_table xcvlocal_cmds[] = {
10323         { "MonitorUI",  xcvlocal_monitorui },
10324         { NULL,         NULL }
10325 };
10326 #else
10327 struct xcv_api_table xcvlocal_cmds[] = {
10328         { NULL,         NULL }
10329 };
10330 #endif
10331
10332
10333
10334 /*******************************************************************
10335 *******************************************************************/
10336
10337 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10338                                        NT_USER_TOKEN *token, const char *command,
10339                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10340                                        uint32_t *needed)
10341 {
10342         int i;
10343
10344         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10345
10346         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10347                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10348                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10349         }
10350         return WERR_BADFUNC;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_XcvData
10355 ****************************************************************/
10356
10357 WERROR _spoolss_XcvData(pipes_struct *p,
10358                         struct spoolss_XcvData *r)
10359 {
10360         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10361         DATA_BLOB out_data = data_blob_null;
10362         WERROR werror;
10363
10364         if (!Printer) {
10365                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10366                         OUR_HANDLE(r->in.handle)));
10367                 return WERR_BADFID;
10368         }
10369
10370         /* Has to be a handle to the TCP/IP port monitor */
10371
10372         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10373                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10374                 return WERR_BADFID;
10375         }
10376
10377         /* requires administrative access to the server */
10378
10379         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10380                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10381                 return WERR_ACCESS_DENIED;
10382         }
10383
10384         /* Allocate the outgoing buffer */
10385
10386         if (r->in.out_data_size) {
10387                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10388                 if (out_data.data == NULL) {
10389                         return WERR_NOMEM;
10390                 }
10391         }
10392
10393         switch ( Printer->printer_type ) {
10394         case SPLHND_PORTMON_TCP:
10395                 werror = process_xcvtcp_command(p->mem_ctx,
10396                                                 p->server_info->ptok,
10397                                                 r->in.function_name,
10398                                                 &r->in.in_data, &out_data,
10399                                                 r->out.needed);
10400                 break;
10401         case SPLHND_PORTMON_LOCAL:
10402                 werror = process_xcvlocal_command(p->mem_ctx,
10403                                                   p->server_info->ptok,
10404                                                   r->in.function_name,
10405                                                   &r->in.in_data, &out_data,
10406                                                   r->out.needed);
10407                 break;
10408         default:
10409                 werror = WERR_INVALID_PRINT_MONITOR;
10410         }
10411
10412         if (!W_ERROR_IS_OK(werror)) {
10413                 return werror;
10414         }
10415
10416         *r->out.status_code = 0;
10417
10418         memcpy(r->out.out_data, out_data.data, out_data.length);
10419
10420         return WERR_OK;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_AddPrintProcessor
10425 ****************************************************************/
10426
10427 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10428                                   struct spoolss_AddPrintProcessor *r)
10429 {
10430         /* for now, just indicate success and ignore the add.  We'll
10431            automatically set the winprint processor for printer
10432            entries later.  Used to debug the LexMark Optra S 1855 PCL
10433            driver --jerry */
10434
10435         return WERR_OK;
10436 }
10437
10438 /****************************************************************
10439  _spoolss_EnumPrinters
10440 ****************************************************************/
10441
10442 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10443                              struct spoolss_EnumPrinters *r)
10444 {
10445         p->rng_fault_state = true;
10446         return WERR_NOT_SUPPORTED;
10447 }
10448
10449 /****************************************************************
10450  _spoolss_AddPrinter
10451 ****************************************************************/
10452
10453 WERROR _spoolss_AddPrinter(pipes_struct *p,
10454                            struct spoolss_AddPrinter *r)
10455 {
10456         p->rng_fault_state = true;
10457         return WERR_NOT_SUPPORTED;
10458 }
10459
10460 /****************************************************************
10461  _spoolss_GetPrinter
10462 ****************************************************************/
10463
10464 WERROR _spoolss_GetPrinter(pipes_struct *p,
10465                            struct spoolss_GetPrinter *r)
10466 {
10467         p->rng_fault_state = true;
10468         return WERR_NOT_SUPPORTED;
10469 }
10470
10471 /****************************************************************
10472  _spoolss_GetPrinterDriver
10473 ****************************************************************/
10474
10475 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10476                                  struct spoolss_GetPrinterDriver *r)
10477 {
10478         p->rng_fault_state = true;
10479         return WERR_NOT_SUPPORTED;
10480 }
10481
10482 /****************************************************************
10483  _spoolss_ReadPrinter
10484 ****************************************************************/
10485
10486 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10487                             struct spoolss_ReadPrinter *r)
10488 {
10489         p->rng_fault_state = true;
10490         return WERR_NOT_SUPPORTED;
10491 }
10492
10493 /****************************************************************
10494  _spoolss_GetPrinterData
10495 ****************************************************************/
10496
10497 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10498                                struct spoolss_GetPrinterData *r)
10499 {
10500         p->rng_fault_state = true;
10501         return WERR_NOT_SUPPORTED;
10502 }
10503
10504 /****************************************************************
10505  _spoolss_SetPrinterData
10506 ****************************************************************/
10507
10508 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10509                                struct spoolss_SetPrinterData *r)
10510 {
10511         p->rng_fault_state = true;
10512         return WERR_NOT_SUPPORTED;
10513 }
10514
10515 /****************************************************************
10516  _spoolss_WaitForPrinterChange
10517 ****************************************************************/
10518
10519 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10520                                      struct spoolss_WaitForPrinterChange *r)
10521 {
10522         p->rng_fault_state = true;
10523         return WERR_NOT_SUPPORTED;
10524 }
10525
10526 /****************************************************************
10527  _spoolss_AddPort
10528 ****************************************************************/
10529
10530 WERROR _spoolss_AddPort(pipes_struct *p,
10531                         struct spoolss_AddPort *r)
10532 {
10533         p->rng_fault_state = true;
10534         return WERR_NOT_SUPPORTED;
10535 }
10536
10537 /****************************************************************
10538  _spoolss_ConfigurePort
10539 ****************************************************************/
10540
10541 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10542                               struct spoolss_ConfigurePort *r)
10543 {
10544         p->rng_fault_state = true;
10545         return WERR_NOT_SUPPORTED;
10546 }
10547
10548 /****************************************************************
10549  _spoolss_DeletePort
10550 ****************************************************************/
10551
10552 WERROR _spoolss_DeletePort(pipes_struct *p,
10553                            struct spoolss_DeletePort *r)
10554 {
10555         p->rng_fault_state = true;
10556         return WERR_NOT_SUPPORTED;
10557 }
10558
10559 /****************************************************************
10560  _spoolss_CreatePrinterIC
10561 ****************************************************************/
10562
10563 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10564                                 struct spoolss_CreatePrinterIC *r)
10565 {
10566         p->rng_fault_state = true;
10567         return WERR_NOT_SUPPORTED;
10568 }
10569
10570 /****************************************************************
10571  _spoolss_PlayGDIScriptOnPrinterIC
10572 ****************************************************************/
10573
10574 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10575                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10576 {
10577         p->rng_fault_state = true;
10578         return WERR_NOT_SUPPORTED;
10579 }
10580
10581 /****************************************************************
10582  _spoolss_DeletePrinterIC
10583 ****************************************************************/
10584
10585 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10586                                 struct spoolss_DeletePrinterIC *r)
10587 {
10588         p->rng_fault_state = true;
10589         return WERR_NOT_SUPPORTED;
10590 }
10591
10592 /****************************************************************
10593  _spoolss_AddPrinterConnection
10594 ****************************************************************/
10595
10596 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10597                                      struct spoolss_AddPrinterConnection *r)
10598 {
10599         p->rng_fault_state = true;
10600         return WERR_NOT_SUPPORTED;
10601 }
10602
10603 /****************************************************************
10604  _spoolss_DeletePrinterConnection
10605 ****************************************************************/
10606
10607 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10608                                         struct spoolss_DeletePrinterConnection *r)
10609 {
10610         p->rng_fault_state = true;
10611         return WERR_NOT_SUPPORTED;
10612 }
10613
10614 /****************************************************************
10615  _spoolss_PrinterMessageBox
10616 ****************************************************************/
10617
10618 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10619                                   struct spoolss_PrinterMessageBox *r)
10620 {
10621         p->rng_fault_state = true;
10622         return WERR_NOT_SUPPORTED;
10623 }
10624
10625 /****************************************************************
10626  _spoolss_AddMonitor
10627 ****************************************************************/
10628
10629 WERROR _spoolss_AddMonitor(pipes_struct *p,
10630                            struct spoolss_AddMonitor *r)
10631 {
10632         p->rng_fault_state = true;
10633         return WERR_NOT_SUPPORTED;
10634 }
10635
10636 /****************************************************************
10637  _spoolss_DeleteMonitor
10638 ****************************************************************/
10639
10640 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10641                               struct spoolss_DeleteMonitor *r)
10642 {
10643         p->rng_fault_state = true;
10644         return WERR_NOT_SUPPORTED;
10645 }
10646
10647 /****************************************************************
10648  _spoolss_DeletePrintProcessor
10649 ****************************************************************/
10650
10651 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10652                                      struct spoolss_DeletePrintProcessor *r)
10653 {
10654         p->rng_fault_state = true;
10655         return WERR_NOT_SUPPORTED;
10656 }
10657
10658 /****************************************************************
10659  _spoolss_AddPrintProvidor
10660 ****************************************************************/
10661
10662 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10663                                  struct spoolss_AddPrintProvidor *r)
10664 {
10665         p->rng_fault_state = true;
10666         return WERR_NOT_SUPPORTED;
10667 }
10668
10669 /****************************************************************
10670  _spoolss_DeletePrintProvidor
10671 ****************************************************************/
10672
10673 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10674                                     struct spoolss_DeletePrintProvidor *r)
10675 {
10676         p->rng_fault_state = true;
10677         return WERR_NOT_SUPPORTED;
10678 }
10679
10680 /****************************************************************
10681  _spoolss_FindFirstPrinterChangeNotification
10682 ****************************************************************/
10683
10684 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10685                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10686 {
10687         p->rng_fault_state = true;
10688         return WERR_NOT_SUPPORTED;
10689 }
10690
10691 /****************************************************************
10692  _spoolss_FindNextPrinterChangeNotification
10693 ****************************************************************/
10694
10695 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10696                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10697 {
10698         p->rng_fault_state = true;
10699         return WERR_NOT_SUPPORTED;
10700 }
10701
10702 /****************************************************************
10703  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10704 ****************************************************************/
10705
10706 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10707                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10708 {
10709         p->rng_fault_state = true;
10710         return WERR_NOT_SUPPORTED;
10711 }
10712
10713 /****************************************************************
10714  _spoolss_ReplyOpenPrinter
10715 ****************************************************************/
10716
10717 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10718                                  struct spoolss_ReplyOpenPrinter *r)
10719 {
10720         p->rng_fault_state = true;
10721         return WERR_NOT_SUPPORTED;
10722 }
10723
10724 /****************************************************************
10725  _spoolss_RouterReplyPrinter
10726 ****************************************************************/
10727
10728 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10729                                    struct spoolss_RouterReplyPrinter *r)
10730 {
10731         p->rng_fault_state = true;
10732         return WERR_NOT_SUPPORTED;
10733 }
10734
10735 /****************************************************************
10736  _spoolss_ReplyClosePrinter
10737 ****************************************************************/
10738
10739 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10740                                   struct spoolss_ReplyClosePrinter *r)
10741 {
10742         p->rng_fault_state = true;
10743         return WERR_NOT_SUPPORTED;
10744 }
10745
10746 /****************************************************************
10747  _spoolss_AddPortEx
10748 ****************************************************************/
10749
10750 WERROR _spoolss_AddPortEx(pipes_struct *p,
10751                           struct spoolss_AddPortEx *r)
10752 {
10753         p->rng_fault_state = true;
10754         return WERR_NOT_SUPPORTED;
10755 }
10756
10757 /****************************************************************
10758  _spoolss_RouterFindFirstPrinterChangeNotification
10759 ****************************************************************/
10760
10761 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10762                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10763 {
10764         p->rng_fault_state = true;
10765         return WERR_NOT_SUPPORTED;
10766 }
10767
10768 /****************************************************************
10769  _spoolss_SpoolerInit
10770 ****************************************************************/
10771
10772 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10773                             struct spoolss_SpoolerInit *r)
10774 {
10775         p->rng_fault_state = true;
10776         return WERR_NOT_SUPPORTED;
10777 }
10778
10779 /****************************************************************
10780  _spoolss_ResetPrinterEx
10781 ****************************************************************/
10782
10783 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10784                                struct spoolss_ResetPrinterEx *r)
10785 {
10786         p->rng_fault_state = true;
10787         return WERR_NOT_SUPPORTED;
10788 }
10789
10790 /****************************************************************
10791  _spoolss_RouterReplyPrinterEx
10792 ****************************************************************/
10793
10794 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10795                                      struct spoolss_RouterReplyPrinterEx *r)
10796 {
10797         p->rng_fault_state = true;
10798         return WERR_NOT_SUPPORTED;
10799 }
10800
10801 /****************************************************************
10802  _spoolss_44
10803 ****************************************************************/
10804
10805 WERROR _spoolss_44(pipes_struct *p,
10806                    struct spoolss_44 *r)
10807 {
10808         p->rng_fault_state = true;
10809         return WERR_NOT_SUPPORTED;
10810 }
10811
10812 /****************************************************************
10813  _spoolss_47
10814 ****************************************************************/
10815
10816 WERROR _spoolss_47(pipes_struct *p,
10817                    struct spoolss_47 *r)
10818 {
10819         p->rng_fault_state = true;
10820         return WERR_NOT_SUPPORTED;
10821 }
10822
10823 /****************************************************************
10824  _spoolss_EnumPrinterData
10825 ****************************************************************/
10826
10827 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10828                                 struct spoolss_EnumPrinterData *r)
10829 {
10830         p->rng_fault_state = true;
10831         return WERR_NOT_SUPPORTED;
10832 }
10833
10834 /****************************************************************
10835  _spoolss_4a
10836 ****************************************************************/
10837
10838 WERROR _spoolss_4a(pipes_struct *p,
10839                    struct spoolss_4a *r)
10840 {
10841         p->rng_fault_state = true;
10842         return WERR_NOT_SUPPORTED;
10843 }
10844
10845 /****************************************************************
10846  _spoolss_4b
10847 ****************************************************************/
10848
10849 WERROR _spoolss_4b(pipes_struct *p,
10850                    struct spoolss_4b *r)
10851 {
10852         p->rng_fault_state = true;
10853         return WERR_NOT_SUPPORTED;
10854 }
10855
10856 /****************************************************************
10857  _spoolss_4c
10858 ****************************************************************/
10859
10860 WERROR _spoolss_4c(pipes_struct *p,
10861                    struct spoolss_4c *r)
10862 {
10863         p->rng_fault_state = true;
10864         return WERR_NOT_SUPPORTED;
10865 }
10866
10867 /****************************************************************
10868  _spoolss_EnumPrinterDataEx
10869 ****************************************************************/
10870
10871 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10872                                   struct spoolss_EnumPrinterDataEx *r)
10873 {
10874         p->rng_fault_state = true;
10875         return WERR_NOT_SUPPORTED;
10876 }
10877
10878 /****************************************************************
10879  _spoolss_EnumPrinterKey
10880 ****************************************************************/
10881
10882 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10883                                struct spoolss_EnumPrinterKey *r)
10884 {
10885         p->rng_fault_state = true;
10886         return WERR_NOT_SUPPORTED;
10887 }
10888
10889 /****************************************************************
10890  _spoolss_53
10891 ****************************************************************/
10892
10893 WERROR _spoolss_53(pipes_struct *p,
10894                    struct spoolss_53 *r)
10895 {
10896         p->rng_fault_state = true;
10897         return WERR_NOT_SUPPORTED;
10898 }
10899
10900 /****************************************************************
10901  _spoolss_55
10902 ****************************************************************/
10903
10904 WERROR _spoolss_55(pipes_struct *p,
10905                    struct spoolss_55 *r)
10906 {
10907         p->rng_fault_state = true;
10908         return WERR_NOT_SUPPORTED;
10909 }
10910
10911 /****************************************************************
10912  _spoolss_56
10913 ****************************************************************/
10914
10915 WERROR _spoolss_56(pipes_struct *p,
10916                    struct spoolss_56 *r)
10917 {
10918         p->rng_fault_state = true;
10919         return WERR_NOT_SUPPORTED;
10920 }
10921
10922 /****************************************************************
10923  _spoolss_57
10924 ****************************************************************/
10925
10926 WERROR _spoolss_57(pipes_struct *p,
10927                    struct spoolss_57 *r)
10928 {
10929         p->rng_fault_state = true;
10930         return WERR_NOT_SUPPORTED;
10931 }
10932
10933 /****************************************************************
10934  _spoolss_5a
10935 ****************************************************************/
10936
10937 WERROR _spoolss_5a(pipes_struct *p,
10938                    struct spoolss_5a *r)
10939 {
10940         p->rng_fault_state = true;
10941         return WERR_NOT_SUPPORTED;
10942 }
10943
10944 /****************************************************************
10945  _spoolss_5b
10946 ****************************************************************/
10947
10948 WERROR _spoolss_5b(pipes_struct *p,
10949                    struct spoolss_5b *r)
10950 {
10951         p->rng_fault_state = true;
10952         return WERR_NOT_SUPPORTED;
10953 }
10954
10955 /****************************************************************
10956  _spoolss_5c
10957 ****************************************************************/
10958
10959 WERROR _spoolss_5c(pipes_struct *p,
10960                    struct spoolss_5c *r)
10961 {
10962         p->rng_fault_state = true;
10963         return WERR_NOT_SUPPORTED;
10964 }
10965
10966 /****************************************************************
10967  _spoolss_5d
10968 ****************************************************************/
10969
10970 WERROR _spoolss_5d(pipes_struct *p,
10971                    struct spoolss_5d *r)
10972 {
10973         p->rng_fault_state = true;
10974         return WERR_NOT_SUPPORTED;
10975 }
10976
10977 /****************************************************************
10978  _spoolss_5e
10979 ****************************************************************/
10980
10981 WERROR _spoolss_5e(pipes_struct *p,
10982                    struct spoolss_5e *r)
10983 {
10984         p->rng_fault_state = true;
10985         return WERR_NOT_SUPPORTED;
10986 }
10987
10988 /****************************************************************
10989  _spoolss_5f
10990 ****************************************************************/
10991
10992 WERROR _spoolss_5f(pipes_struct *p,
10993                    struct spoolss_5f *r)
10994 {
10995         p->rng_fault_state = true;
10996         return WERR_NOT_SUPPORTED;
10997 }
10998