925b15eba9b5aa22c944c7886d126c1c96fc210f
[jra/samba/.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
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  * construct_printer_info1
4486  * fill a spoolss_PrinterInfo1 struct
4487 ********************************************************************/
4488
4489 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4490                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4491                                       uint32_t flags,
4492                                       struct spoolss_PrinterInfo1 *r,
4493                                       int snum)
4494 {
4495         char *chaine = NULL;
4496         r->flags                = flags;
4497
4498         if (*ntprinter->info_2->comment == '\0') {
4499                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4500                 chaine = talloc_asprintf(mem_ctx,
4501                                 "%s,%s,%s", ntprinter->info_2->printername,
4502                                 ntprinter->info_2->drivername, lp_comment(snum));
4503         } else {
4504                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4505                 chaine = talloc_asprintf(mem_ctx,
4506                                 "%s,%s,%s", ntprinter->info_2->printername,
4507                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4508         }
4509         W_ERROR_HAVE_NO_MEMORY(chaine);
4510         W_ERROR_HAVE_NO_MEMORY(r->comment);
4511
4512         r->description          = talloc_strdup(mem_ctx, chaine);
4513         W_ERROR_HAVE_NO_MEMORY(r->description);
4514         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4515         W_ERROR_HAVE_NO_MEMORY(r->name);
4516
4517         return WERR_OK;
4518 }
4519
4520 /********************************************************************
4521  * construct_printer_info2
4522  * fill a spoolss_PrinterInfo2 struct
4523 ********************************************************************/
4524
4525 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4526                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4527                                       struct spoolss_PrinterInfo2 *r,
4528                                       int snum)
4529 {
4530         int count;
4531
4532         print_status_struct status;
4533
4534         count = print_queue_length(snum, &status);
4535
4536         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4537         W_ERROR_HAVE_NO_MEMORY(r->servername);
4538         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4539         W_ERROR_HAVE_NO_MEMORY(r->printername);
4540         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4541         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4542         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4543         W_ERROR_HAVE_NO_MEMORY(r->portname);
4544         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4545         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4546
4547         if (*ntprinter->info_2->comment == '\0') {
4548                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4549         } else {
4550                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4551         }
4552         W_ERROR_HAVE_NO_MEMORY(r->comment);
4553
4554         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4555         W_ERROR_HAVE_NO_MEMORY(r->location);
4556         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4557         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4558         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4559         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4560         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4561         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4562         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4563         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4564
4565         r->attributes           = ntprinter->info_2->attributes;
4566
4567         r->priority             = ntprinter->info_2->priority;
4568         r->defaultpriority      = ntprinter->info_2->default_priority;
4569         r->starttime            = ntprinter->info_2->starttime;
4570         r->untiltime            = ntprinter->info_2->untiltime;
4571         r->status               = nt_printq_status(status.status);
4572         r->cjobs                = count;
4573         r->averageppm           = ntprinter->info_2->averageppm;
4574
4575         r->devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
4576         if (!r->devmode) {
4577                 DEBUG(8,("Returning NULL Devicemode!\n"));
4578         }
4579
4580         r->secdesc              = NULL;
4581
4582         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4583                 /* don't use talloc_steal() here unless you do a deep steal of all
4584                    the SEC_DESC members */
4585
4586                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4587         }
4588
4589         return WERR_OK;
4590 }
4591
4592 /********************************************************************
4593  Spoolss_enumprinters.
4594 ********************************************************************/
4595
4596 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4597                                        uint32_t flags,
4598                                        union spoolss_PrinterInfo **info_p,
4599                                        uint32_t *count)
4600 {
4601         int snum;
4602         int n_services = lp_numservices();
4603         union spoolss_PrinterInfo *info = NULL;
4604         WERROR result = WERR_OK;
4605
4606         DEBUG(4,("enum_all_printers_info_1\n"));
4607
4608         *count = 0;
4609
4610         for (snum=0; snum<n_services; snum++) {
4611                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4612
4613                         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4614                         struct spoolss_PrinterInfo1 info1;
4615
4616                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4617
4618                         result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4619                         if (!W_ERROR_IS_OK(result)) {
4620                                 continue;
4621                         }
4622
4623                         result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4624                         free_a_printer(&ntprinter,2);
4625                         if (!W_ERROR_IS_OK(result)) {
4626                                 continue;
4627                         }
4628
4629                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4630                                                     union spoolss_PrinterInfo,
4631                                                     *count + 1);
4632                         if (!info) {
4633                                 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4634                                 result = WERR_NOMEM;
4635                                 goto out;
4636                         }
4637
4638                         DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4639
4640                         info[*count].info1 = info1;
4641                         (*count)++;
4642                 }
4643         }
4644
4645  out:
4646         if (!W_ERROR_IS_OK(result)) {
4647                 TALLOC_FREE(info);
4648                 *count = 0;
4649                 return result;
4650         }
4651
4652         *info_p = info;
4653
4654         return WERR_OK;
4655 }
4656
4657 /********************************************************************
4658  enum_all_printers_info_1_local.
4659 *********************************************************************/
4660
4661 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4662                                              union spoolss_PrinterInfo **info,
4663                                              uint32_t *count)
4664 {
4665         DEBUG(4,("enum_all_printers_info_1_local\n"));
4666
4667         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4668 }
4669
4670 /********************************************************************
4671  enum_all_printers_info_1_name.
4672 *********************************************************************/
4673
4674 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4675                                             const char *name,
4676                                             union spoolss_PrinterInfo **info,
4677                                             uint32_t *count)
4678 {
4679         const char *s = name;
4680
4681         DEBUG(4,("enum_all_printers_info_1_name\n"));
4682
4683         if ((name[0] == '\\') && (name[1] == '\\')) {
4684                 s = name + 2;
4685         }
4686
4687         if (!is_myname_or_ipaddr(s)) {
4688                 return WERR_INVALID_NAME;
4689         }
4690
4691         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4692 }
4693
4694 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4695 /********************************************************************
4696  enum_all_printers_info_1_remote.
4697 *********************************************************************/
4698
4699 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4700 {
4701         PRINTER_INFO_1 *printer;
4702         fstring printername;
4703         fstring desc;
4704         fstring comment;
4705         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4706         WERROR result = WERR_OK;
4707
4708         /* JFM: currently it's more a place holder than anything else.
4709          * In the spooler world there is a notion of server registration.
4710          * the print servers are registered on the PDC (in the same domain)
4711          *
4712          * We should have a TDB here. The registration is done thru an
4713          * undocumented RPC call.
4714          */
4715
4716         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4717                 return WERR_NOMEM;
4718
4719         *returned=1;
4720
4721         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4722         slprintf(desc, sizeof(desc)-1,"%s", name);
4723         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4724
4725         init_unistr(&printer->description, desc);
4726         init_unistr(&printer->name, printername);
4727         init_unistr(&printer->comment, comment);
4728         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4729
4730         /* check the required size. */
4731         *needed += spoolss_size_printer_info_1(printer);
4732
4733         if (*needed > offered) {
4734                 result = WERR_INSUFFICIENT_BUFFER;
4735                 goto out;
4736         }
4737
4738         if (!rpcbuf_alloc_size(buffer, *needed)) {
4739                 result = WERR_NOMEM;
4740                 goto out;
4741         }
4742
4743         /* fill the buffer with the structures */
4744         smb_io_printer_info_1("", buffer, printer, 0);
4745
4746 out:
4747         /* clear memory */
4748         SAFE_FREE(printer);
4749
4750         if ( !W_ERROR_IS_OK(result) )
4751                 *returned = 0;
4752
4753         return result;
4754 }
4755
4756 #endif
4757
4758 /********************************************************************
4759  enum_all_printers_info_1_network.
4760 *********************************************************************/
4761
4762 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4763                                                const char *name,
4764                                                union spoolss_PrinterInfo **info,
4765                                                uint32_t *count)
4766 {
4767         const char *s = name;
4768
4769         DEBUG(4,("enum_all_printers_info_1_network\n"));
4770
4771         /* If we respond to a enum_printers level 1 on our name with flags
4772            set to PRINTER_ENUM_REMOTE with a list of printers then these
4773            printers incorrectly appear in the APW browse list.
4774            Specifically the printers for the server appear at the workgroup
4775            level where all the other servers in the domain are
4776            listed. Windows responds to this call with a
4777            WERR_CAN_NOT_COMPLETE so we should do the same. */
4778
4779         if (name[0] == '\\' && name[1] == '\\') {
4780                  s = name + 2;
4781         }
4782
4783         if (is_myname_or_ipaddr(s)) {
4784                  return WERR_CAN_NOT_COMPLETE;
4785         }
4786
4787         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4788 }
4789
4790 /********************************************************************
4791  * api_spoolss_enumprinters
4792  *
4793  * called from api_spoolss_enumprinters (see this to understand)
4794  ********************************************************************/
4795
4796 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4797                                        union spoolss_PrinterInfo **info_p,
4798                                        uint32_t *count)
4799 {
4800         int snum;
4801         int n_services = lp_numservices();
4802         union spoolss_PrinterInfo *info = NULL;
4803         WERROR result = WERR_OK;
4804
4805         *count = 0;
4806
4807         for (snum=0; snum<n_services; snum++) {
4808                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum)) {
4809
4810                         struct spoolss_PrinterInfo2 info2;
4811                         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4812
4813                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4814
4815                         result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4816                         if (!W_ERROR_IS_OK(result)) {
4817                                 continue;
4818                         }
4819
4820                         result = construct_printer_info2(info, ntprinter, &info2, snum);
4821                         free_a_printer(&ntprinter, 2);
4822                         if (!W_ERROR_IS_OK(result)) {
4823                                 continue;
4824                         }
4825
4826                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4827                                                     union spoolss_PrinterInfo,
4828                                                     *count + 1);
4829                         if (!info) {
4830                                 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4831                                 result = WERR_NOMEM;
4832                                 goto out;
4833                         }
4834
4835                         DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4836
4837                         info[*count].info2 = info2;
4838
4839                         (*count)++;
4840                 }
4841         }
4842
4843  out:
4844         if (!W_ERROR_IS_OK(result)) {
4845                 TALLOC_FREE(info);
4846                 *count = 0;
4847                 return result;
4848         }
4849
4850         *info_p = info;
4851
4852         return WERR_OK;
4853 }
4854
4855 /********************************************************************
4856  * handle enumeration of printers at level 1
4857  ********************************************************************/
4858
4859 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4860                                   uint32_t flags,
4861                                   const char *name,
4862                                   union spoolss_PrinterInfo **info,
4863                                   uint32_t *count)
4864 {
4865         /* Not all the flags are equals */
4866
4867         if (flags & PRINTER_ENUM_LOCAL) {
4868                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4869         }
4870
4871         if (flags & PRINTER_ENUM_NAME) {
4872                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4873         }
4874
4875 #if 0   /* JERRY - disabled for now */
4876         if (flags & PRINTER_ENUM_REMOTE) {
4877                 return enum_all_printers_info_1_remote(mem_ctx, name, info, count);
4878         }
4879 #endif
4880
4881         if (flags & PRINTER_ENUM_NETWORK) {
4882                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4883         }
4884
4885         return WERR_OK; /* NT4sp5 does that */
4886 }
4887
4888 /********************************************************************
4889  * handle enumeration of printers at level 2
4890  ********************************************************************/
4891
4892 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4893                                   uint32_t flags,
4894                                   const char *servername,
4895                                   union spoolss_PrinterInfo **info,
4896                                   uint32_t *count)
4897 {
4898         if (flags & PRINTER_ENUM_LOCAL) {
4899                 return enum_all_printers_info_2(mem_ctx, info, count);
4900         }
4901
4902         if (flags & PRINTER_ENUM_NAME) {
4903                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4904                         return WERR_INVALID_NAME;
4905                 }
4906
4907                 return enum_all_printers_info_2(mem_ctx, info, count);
4908         }
4909
4910         if (flags & PRINTER_ENUM_REMOTE) {
4911                 return WERR_UNKNOWN_LEVEL;
4912         }
4913
4914         return WERR_OK;
4915 }
4916
4917 /********************************************************************
4918  * handle enumeration of printers at level 5
4919  ********************************************************************/
4920
4921 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4922                                   uint32_t flags,
4923                                   const char *servername,
4924                                   union spoolss_PrinterInfo **info,
4925                                   uint32_t *count)
4926 {
4927 /*      return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4928         return WERR_OK;
4929 }
4930
4931 /****************************************************************
4932  _spoolss_EnumPrinters
4933 ****************************************************************/
4934
4935 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4936                              struct spoolss_EnumPrinters *r)
4937 {
4938         const char *name;
4939         WERROR result;
4940
4941         /* that's an [in out] buffer */
4942
4943         if (!r->in.buffer && (r->in.offered != 0)) {
4944                 return WERR_INVALID_PARAM;
4945         }
4946
4947         DEBUG(4,("_spoolss_EnumPrinters\n"));
4948
4949         *r->out.needed = 0;
4950         *r->out.count = 0;
4951         *r->out.info = NULL;
4952
4953         /*
4954          * Level 1:
4955          *          flags==PRINTER_ENUM_NAME
4956          *           if name=="" then enumerates all printers
4957          *           if name!="" then enumerate the printer
4958          *          flags==PRINTER_ENUM_REMOTE
4959          *          name is NULL, enumerate printers
4960          * Level 2: name!="" enumerates printers, name can't be NULL
4961          * Level 3: doesn't exist
4962          * Level 4: does a local registry lookup
4963          * Level 5: same as Level 2
4964          */
4965
4966         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4967         W_ERROR_HAVE_NO_MEMORY(name);
4968
4969         switch (r->in.level) {
4970         case 1:
4971                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4972                                              r->out.info, r->out.count);
4973                 break;
4974         case 2:
4975                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4976                                              r->out.info, r->out.count);
4977                 break;
4978         case 5:
4979                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4980                                              r->out.info, r->out.count);
4981                 break;
4982         case 3:
4983         case 4:
4984                 result = WERR_OK; /* ??? */
4985                 break;
4986         default:
4987                 return WERR_UNKNOWN_LEVEL;
4988         }
4989
4990         if (!W_ERROR_IS_OK(result)) {
4991                 return result;
4992         }
4993
4994         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4995                                                      spoolss_EnumPrinters, NULL,
4996                                                      *r->out.info, r->in.level,
4997                                                      *r->out.count);
4998         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4999         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
5000
5001         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5002 }
5003
5004 /****************************************************************************
5005 ****************************************************************************/
5006
5007 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5008 {
5009         PRINTER_INFO_0 *printer=NULL;
5010         WERROR result = WERR_OK;
5011
5012         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
5013                 return WERR_NOMEM;
5014
5015         construct_printer_info_0(print_hnd, printer, snum);
5016
5017         /* check the required size. */
5018         *needed += spoolss_size_printer_info_0(printer);
5019
5020         if (*needed > offered) {
5021                 result = WERR_INSUFFICIENT_BUFFER;
5022                 goto out;
5023         }
5024
5025         if (!rpcbuf_alloc_size(buffer, *needed)) {
5026                 result = WERR_NOMEM;
5027                 goto out;
5028         }
5029
5030         /* fill the buffer with the structures */
5031         smb_io_printer_info_0("", buffer, printer, 0);
5032
5033 out:
5034         /* clear memory */
5035
5036         SAFE_FREE(printer);
5037
5038         return result;
5039 }
5040
5041 /****************************************************************************
5042 ****************************************************************************/
5043
5044 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5045 {
5046         PRINTER_INFO_1 *printer=NULL;
5047         WERROR result = WERR_OK;
5048
5049         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
5050                 return WERR_NOMEM;
5051
5052         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
5053
5054         /* check the required size. */
5055         *needed += spoolss_size_printer_info_1(printer);
5056
5057         if (*needed > offered) {
5058                 result = WERR_INSUFFICIENT_BUFFER;
5059                 goto out;
5060         }
5061
5062         if (!rpcbuf_alloc_size(buffer, *needed)) {
5063                 result = WERR_NOMEM;
5064                 goto out;
5065         }
5066
5067         /* fill the buffer with the structures */
5068         smb_io_printer_info_1("", buffer, printer, 0);
5069
5070 out:
5071         /* clear memory */
5072         SAFE_FREE(printer);
5073
5074         return result;
5075 }
5076
5077 /****************************************************************************
5078 ****************************************************************************/
5079
5080 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5081 {
5082         PRINTER_INFO_2 *printer=NULL;
5083         WERROR result = WERR_OK;
5084
5085         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
5086                 return WERR_NOMEM;
5087
5088         construct_printer_info_2(print_hnd, printer, snum);
5089
5090         /* check the required size. */
5091         *needed += spoolss_size_printer_info_2(printer);
5092
5093         if (*needed > offered) {
5094                 result = WERR_INSUFFICIENT_BUFFER;
5095                 goto out;
5096         }
5097
5098         if (!rpcbuf_alloc_size(buffer, *needed)) {
5099                 result = WERR_NOMEM;
5100                 goto out;
5101         }
5102
5103         /* fill the buffer with the structures */
5104         if (!smb_io_printer_info_2("", buffer, printer, 0))
5105                 result = WERR_NOMEM;
5106
5107 out:
5108         /* clear memory */
5109         free_printer_info_2(printer);
5110
5111         return result;
5112 }
5113
5114 /****************************************************************************
5115 ****************************************************************************/
5116
5117 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5118 {
5119         PRINTER_INFO_3 *printer=NULL;
5120         WERROR result = WERR_OK;
5121
5122         if (!construct_printer_info_3(print_hnd, &printer, snum))
5123                 return WERR_NOMEM;
5124
5125         /* check the required size. */
5126         *needed += spoolss_size_printer_info_3(printer);
5127
5128         if (*needed > offered) {
5129                 result = WERR_INSUFFICIENT_BUFFER;
5130                 goto out;
5131         }
5132
5133         if (!rpcbuf_alloc_size(buffer, *needed)) {
5134                 result = WERR_NOMEM;
5135                 goto out;
5136         }
5137
5138         /* fill the buffer with the structures */
5139         smb_io_printer_info_3("", buffer, printer, 0);
5140
5141 out:
5142         /* clear memory */
5143         free_printer_info_3(printer);
5144
5145         return result;
5146 }
5147
5148 /****************************************************************************
5149 ****************************************************************************/
5150
5151 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5152 {
5153         PRINTER_INFO_4 *printer=NULL;
5154         WERROR result = WERR_OK;
5155
5156         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
5157                 return WERR_NOMEM;
5158
5159         if (!construct_printer_info_4(print_hnd, printer, snum)) {
5160                 SAFE_FREE(printer);
5161                 return WERR_NOMEM;
5162         }
5163
5164         /* check the required size. */
5165         *needed += spoolss_size_printer_info_4(printer);
5166
5167         if (*needed > offered) {
5168                 result = WERR_INSUFFICIENT_BUFFER;
5169                 goto out;
5170         }
5171
5172         if (!rpcbuf_alloc_size(buffer, *needed)) {
5173                 result = WERR_NOMEM;
5174                 goto out;
5175         }
5176
5177         /* fill the buffer with the structures */
5178         smb_io_printer_info_4("", buffer, printer, 0);
5179
5180 out:
5181         /* clear memory */
5182         free_printer_info_4(printer);
5183
5184         return result;
5185 }
5186
5187 /****************************************************************************
5188 ****************************************************************************/
5189
5190 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5191 {
5192         PRINTER_INFO_5 *printer=NULL;
5193         WERROR result = WERR_OK;
5194
5195         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
5196                 return WERR_NOMEM;
5197
5198         if (!construct_printer_info_5(print_hnd, printer, snum)) {
5199                 free_printer_info_5(printer);
5200                 return WERR_NOMEM;
5201         }
5202
5203         /* check the required size. */
5204         *needed += spoolss_size_printer_info_5(printer);
5205
5206         if (*needed > offered) {
5207                 result = WERR_INSUFFICIENT_BUFFER;
5208                 goto out;
5209         }
5210
5211         if (!rpcbuf_alloc_size(buffer, *needed)) {
5212                 result = WERR_NOMEM;
5213                 goto out;
5214         }
5215
5216         /* fill the buffer with the structures */
5217         smb_io_printer_info_5("", buffer, printer, 0);
5218
5219 out:
5220         /* clear memory */
5221         free_printer_info_5(printer);
5222
5223         return result;
5224 }
5225
5226 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5227                                  int snum,
5228                                  RPC_BUFFER *buffer, uint32 offered,
5229                                  uint32 *needed)
5230 {
5231         PRINTER_INFO_6 *printer;
5232         WERROR result = WERR_OK;
5233
5234         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5235                 return WERR_NOMEM;
5236         }
5237
5238         if (!construct_printer_info_6(print_hnd, printer, snum)) {
5239                 free_printer_info_6(printer);
5240                 return WERR_NOMEM;
5241         }
5242
5243         /* check the required size. */
5244         *needed += spoolss_size_printer_info_6(printer);
5245
5246         if (*needed > offered) {
5247                 result = WERR_INSUFFICIENT_BUFFER;
5248                 goto out;
5249         }
5250
5251         if (!rpcbuf_alloc_size(buffer, *needed)) {
5252                 result = WERR_NOMEM;
5253                 goto out;
5254         }
5255
5256         /* fill the buffer with the structures */
5257         smb_io_printer_info_6("", buffer, printer, 0);
5258
5259 out:
5260         /* clear memory */
5261         free_printer_info_6(printer);
5262
5263         return result;
5264 }
5265
5266 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5267 {
5268         PRINTER_INFO_7 *printer=NULL;
5269         WERROR result = WERR_OK;
5270
5271         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5272                 return WERR_NOMEM;
5273
5274         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5275                 result = WERR_NOMEM;
5276                 goto out;
5277         }
5278
5279         /* check the required size. */
5280         *needed += spoolss_size_printer_info_7(printer);
5281
5282         if (*needed > offered) {
5283                 result = WERR_INSUFFICIENT_BUFFER;
5284                 goto out;
5285         }
5286
5287         if (!rpcbuf_alloc_size(buffer, *needed)) {
5288                 result = WERR_NOMEM;
5289                 goto out;
5290
5291         }
5292
5293         /* fill the buffer with the structures */
5294         smb_io_printer_info_7("", buffer, printer, 0);
5295
5296 out:
5297         /* clear memory */
5298         free_printer_info_7(printer);
5299
5300         return result;
5301 }
5302
5303 /****************************************************************************
5304 ****************************************************************************/
5305
5306 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5307 {
5308         POLICY_HND *handle = &q_u->handle;
5309         uint32 level = q_u->level;
5310         RPC_BUFFER *buffer = NULL;
5311         uint32 offered = q_u->offered;
5312         uint32 *needed = &r_u->needed;
5313         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5314
5315         int snum;
5316
5317         /* that's an [in out] buffer */
5318
5319         if (!q_u->buffer && (offered!=0)) {
5320                 return WERR_INVALID_PARAM;
5321         }
5322
5323         if (offered > MAX_RPC_DATA_SIZE) {
5324                 return WERR_INVALID_PARAM;
5325         }
5326
5327         rpcbuf_move(q_u->buffer, &r_u->buffer);
5328         buffer = r_u->buffer;
5329
5330         *needed=0;
5331
5332         if (!get_printer_snum(p, handle, &snum, NULL))
5333                 return WERR_BADFID;
5334
5335         switch (level) {
5336         case 0:
5337                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5338         case 1:
5339                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5340         case 2:
5341                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5342         case 3:
5343                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5344         case 4:
5345                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5346         case 5:
5347                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5348         case 6:
5349                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5350         case 7:
5351                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5352         }
5353         return WERR_UNKNOWN_LEVEL;
5354 }
5355
5356 /********************************************************************
5357  ********************************************************************/
5358
5359 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5360                                                   fstring *fstring_array,
5361                                                   const char *cservername)
5362 {
5363         int i, num_strings = 0;
5364         const char **array = NULL;
5365
5366         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
5367
5368                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
5369                                                   cservername, fstring_array[i]);
5370                 if (!str) {
5371                         TALLOC_FREE(array);
5372                         return NULL;
5373                 }
5374
5375
5376                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5377                         TALLOC_FREE(array);
5378                         return NULL;
5379                 }
5380         }
5381
5382         if (i > 0) {
5383                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5384                              &array, &num_strings);
5385         }
5386
5387         return array;
5388 }
5389
5390 /********************************************************************
5391  * fill a spoolss_DriverInfo1 struct
5392  ********************************************************************/
5393
5394 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5395                                         struct spoolss_DriverInfo1 *r,
5396                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5397                                         const char *servername,
5398                                         const char *architecture)
5399 {
5400         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5401         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5402
5403         return WERR_OK;
5404 }
5405
5406 /********************************************************************
5407  * fill a spoolss_DriverInfo2 struct
5408  ********************************************************************/
5409
5410 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5411                                         struct spoolss_DriverInfo2 *r,
5412                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5413                                         const char *servername)
5414
5415 {
5416         const char *cservername = canon_servername(servername);
5417
5418         r->version              = driver->info_3->cversion;
5419
5420         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5421         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5422         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5423         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5424
5425         if (strlen(driver->info_3->driverpath)) {
5426                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5427                                 cservername, driver->info_3->driverpath);
5428         } else {
5429                 r->driver_path  = talloc_strdup(mem_ctx, "");
5430         }
5431         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5432
5433         if (strlen(driver->info_3->datafile)) {
5434                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5435                                 cservername, driver->info_3->datafile);
5436         } else {
5437                 r->data_file    = talloc_strdup(mem_ctx, "");
5438         }
5439         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5440
5441         if (strlen(driver->info_3->configfile)) {
5442                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5443                                 cservername, driver->info_3->configfile);
5444         } else {
5445                 r->config_file  = talloc_strdup(mem_ctx, "");
5446         }
5447         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5448
5449         return WERR_OK;
5450 }
5451
5452 /********************************************************************
5453  * fill a spoolss_DriverInfo3 struct
5454  ********************************************************************/
5455
5456 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5457                                         struct spoolss_DriverInfo3 *r,
5458                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5459                                         const char *servername)
5460 {
5461         const char *cservername = canon_servername(servername);
5462
5463         r->version              = driver->info_3->cversion;
5464
5465         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5466         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5467         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5468         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5469
5470         if (strlen(driver->info_3->driverpath)) {
5471                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5472                                 cservername, driver->info_3->driverpath);
5473         } else {
5474                 r->driver_path  = talloc_strdup(mem_ctx, "");
5475         }
5476         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5477
5478         if (strlen(driver->info_3->datafile)) {
5479                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5480                                 cservername, driver->info_3->datafile);
5481         } else {
5482                 r->data_file    = talloc_strdup(mem_ctx, "");
5483         }
5484         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5485
5486         if (strlen(driver->info_3->configfile)) {
5487                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5488                                 cservername, driver->info_3->configfile);
5489         } else {
5490                 r->config_file  = talloc_strdup(mem_ctx, "");
5491         }
5492         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5493
5494         if (strlen(driver->info_3->helpfile)) {
5495                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5496                                 cservername, driver->info_3->helpfile);
5497         } else {
5498                 r->help_file    = talloc_strdup(mem_ctx, "");
5499         }
5500         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5501
5502         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5503         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5504         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5505         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5506
5507         r->dependent_files = string_array_from_driver_info(mem_ctx,
5508                                                            driver->info_3->dependentfiles,
5509                                                            cservername);
5510         return WERR_OK;
5511 }
5512
5513 /********************************************************************
5514  * fill a spoolss_DriverInfo6 struct
5515  ********************************************************************/
5516
5517 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5518                                         struct spoolss_DriverInfo6 *r,
5519                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5520                                         const char *servername)
5521 {
5522         const char *cservername = canon_servername(servername);
5523
5524         r->version              = driver->info_3->cversion;
5525
5526         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5527         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5528         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5529         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5530
5531         if (strlen(driver->info_3->driverpath)) {
5532                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5533                                 cservername, driver->info_3->driverpath);
5534         } else {
5535                 r->driver_path  = talloc_strdup(mem_ctx, "");
5536         }
5537         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5538
5539         if (strlen(driver->info_3->datafile)) {
5540                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5541                                 cservername, driver->info_3->datafile);
5542         } else {
5543                 r->data_file    = talloc_strdup(mem_ctx, "");
5544         }
5545         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5546
5547         if (strlen(driver->info_3->configfile)) {
5548                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5549                                 cservername, driver->info_3->configfile);
5550         } else {
5551                 r->config_file  = talloc_strdup(mem_ctx, "");
5552         }
5553         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5554
5555         if (strlen(driver->info_3->helpfile)) {
5556                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5557                                 cservername, driver->info_3->helpfile);
5558         } else {
5559                 r->help_file    = talloc_strdup(mem_ctx, "");
5560         }
5561         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5562
5563         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5564         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5565         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5566         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5567
5568         r->dependent_files = string_array_from_driver_info(mem_ctx,
5569                                                            driver->info_3->dependentfiles,
5570                                                            cservername);
5571         r->previous_names = string_array_from_driver_info(mem_ctx,
5572                                                           NULL,
5573                                                           cservername);
5574
5575         r->driver_date          = 0;
5576         r->driver_version       = 0;
5577
5578         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5579         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5580         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5581         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5582         r->hardware_id          = talloc_strdup(mem_ctx, "");
5583         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5584         r->provider             = talloc_strdup(mem_ctx, "");
5585         W_ERROR_HAVE_NO_MEMORY(r->provider);
5586
5587         return WERR_OK;
5588 }
5589
5590 /********************************************************************
5591  * construct_printer_driver_info_1
5592  ********************************************************************/
5593
5594 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5595                                               struct spoolss_DriverInfo1 *r,
5596                                               int snum,
5597                                               const char *servername,
5598                                               const char *architecture,
5599                                               uint32_t version)
5600 {
5601         NT_PRINTER_INFO_LEVEL *printer = NULL;
5602         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5603         WERROR result;
5604
5605         ZERO_STRUCT(driver);
5606
5607         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5608                 return WERR_INVALID_PRINTER_NAME;
5609
5610         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5611                 free_a_printer(&printer, 2);
5612                 return WERR_UNKNOWN_PRINTER_DRIVER;
5613         }
5614
5615         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5616
5617         free_a_printer(&printer,2);
5618
5619         return result;
5620 }
5621
5622 /********************************************************************
5623  * construct_printer_driver_info_2
5624  * fill a printer_info_2 struct
5625  ********************************************************************/
5626
5627 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5628                                               struct spoolss_DriverInfo2 *r,
5629                                               int snum,
5630                                               const char *servername,
5631                                               const char *architecture,
5632                                               uint32_t version)
5633 {
5634         NT_PRINTER_INFO_LEVEL *printer = NULL;
5635         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5636         WERROR result;
5637
5638         ZERO_STRUCT(printer);
5639         ZERO_STRUCT(driver);
5640
5641         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5642                 return WERR_INVALID_PRINTER_NAME;
5643
5644         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5645                 free_a_printer(&printer, 2);
5646                 return WERR_UNKNOWN_PRINTER_DRIVER;
5647         }
5648
5649         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5650
5651         free_a_printer(&printer,2);
5652
5653         return result;
5654 }
5655
5656 /********************************************************************
5657  * copy a strings array and convert to UNICODE
5658  *
5659  * convert an array of ascii string to a UNICODE string
5660  ********************************************************************/
5661
5662 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5663 {
5664         int i=0;
5665         int j=0;
5666         const char *v;
5667         char *line = NULL;
5668         TALLOC_CTX *ctx = talloc_tos();
5669
5670         DEBUG(6,("init_unistr_array\n"));
5671         *uni_array=NULL;
5672
5673         while (true) {
5674                 if ( !char_array ) {
5675                         v = "";
5676                 } else {
5677                         v = char_array[i];
5678                         if (!v)
5679                                 v = ""; /* hack to handle null lists */
5680                 }
5681
5682                 /* hack to allow this to be used in places other than when generating
5683                    the list of dependent files */
5684
5685                 TALLOC_FREE(line);
5686                 if ( servername ) {
5687                         line = talloc_asprintf(ctx,
5688                                         "\\\\%s%s",
5689                                         canon_servername(servername),
5690                                         v);
5691                 } else {
5692                         line = talloc_strdup(ctx, v);
5693                 }
5694
5695                 if (!line) {
5696                         SAFE_FREE(*uni_array);
5697                         return 0;
5698                 }
5699                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5700
5701                 /* add one extra unit16 for the second terminating NULL */
5702
5703                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5704                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5705                         return 0;
5706                 }
5707
5708                 if ( !strlen(v) )
5709                         break;
5710
5711                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5712                 i++;
5713         }
5714
5715         if (*uni_array) {
5716                 /* special case for ""; we need to add both NULL's here */
5717                 if (!j)
5718                         (*uni_array)[j++]=0x0000;
5719                 (*uni_array)[j]=0x0000;
5720         }
5721
5722         DEBUGADD(6,("last one:done\n"));
5723
5724         /* return size of array in uint16's */
5725
5726         return j+1;
5727 }
5728
5729 /********************************************************************
5730  * construct_printer_info_3
5731  * fill a printer_info_3 struct
5732  ********************************************************************/
5733
5734 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5735                                               struct spoolss_DriverInfo3 *r,
5736                                               int snum,
5737                                               const char *servername,
5738                                               const char *architecture,
5739                                               uint32_t version)
5740 {
5741         NT_PRINTER_INFO_LEVEL *printer = NULL;
5742         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5743         WERROR status;
5744         ZERO_STRUCT(driver);
5745
5746         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5747         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5748         if (!W_ERROR_IS_OK(status))
5749                 return WERR_INVALID_PRINTER_NAME;
5750
5751         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5752         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5753
5754 #if 0   /* JERRY */
5755
5756         /*
5757          * I put this code in during testing.  Helpful when commenting out the
5758          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5759          * as win2k always queries the driver using an infor level of 6.
5760          * I've left it in (but ifdef'd out) because I'll probably
5761          * use it in experimentation again in the future.   --jerry 22/01/2002
5762          */
5763
5764         if (!W_ERROR_IS_OK(status)) {
5765                 /*
5766                  * Is this a W2k client ?
5767                  */
5768                 if (version == 3) {
5769                         /* Yes - try again with a WinNT driver. */
5770                         version = 2;
5771                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5772                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5773                 }
5774 #endif
5775
5776                 if (!W_ERROR_IS_OK(status)) {
5777                         free_a_printer(&printer,2);
5778                         return WERR_UNKNOWN_PRINTER_DRIVER;
5779                 }
5780
5781 #if 0   /* JERRY */
5782         }
5783 #endif
5784
5785
5786         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5787
5788         free_a_printer(&printer,2);
5789
5790         return status;
5791 }
5792
5793 /********************************************************************
5794  * construct_printer_info_6
5795  * fill a printer_info_6 struct
5796  ********************************************************************/
5797
5798 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5799                                               struct spoolss_DriverInfo6 *r,
5800                                               int snum,
5801                                               const char *servername,
5802                                               const char *architecture,
5803                                               uint32_t version)
5804 {
5805         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5806         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5807         WERROR                          status;
5808
5809         ZERO_STRUCT(driver);
5810
5811         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5812
5813         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5814
5815         if (!W_ERROR_IS_OK(status))
5816                 return WERR_INVALID_PRINTER_NAME;
5817
5818         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5819
5820         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5821
5822         if (!W_ERROR_IS_OK(status))
5823         {
5824                 /*
5825                  * Is this a W2k client ?
5826                  */
5827
5828                 if (version < 3) {
5829                         free_a_printer(&printer,2);
5830                         return WERR_UNKNOWN_PRINTER_DRIVER;
5831                 }
5832
5833                 /* Yes - try again with a WinNT driver. */
5834                 version = 2;
5835                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5836                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5837                 if (!W_ERROR_IS_OK(status)) {
5838                         free_a_printer(&printer,2);
5839                         return WERR_UNKNOWN_PRINTER_DRIVER;
5840                 }
5841         }
5842
5843         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5844
5845         free_a_printer(&printer,2);
5846         free_a_printer_driver(driver, 3);
5847
5848         return status;
5849 }
5850
5851 /****************************************************************
5852  _spoolss_GetPrinterDriver2
5853 ****************************************************************/
5854
5855 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5856                                   struct spoolss_GetPrinterDriver2 *r)
5857 {
5858         Printer_entry *printer;
5859         WERROR result;
5860
5861         const char *servername;
5862         int snum;
5863
5864         /* that's an [in out] buffer */
5865
5866         if (!r->in.buffer && (r->in.offered != 0)) {
5867                 return WERR_INVALID_PARAM;
5868         }
5869
5870         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5871
5872         if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5873                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5874                 return WERR_INVALID_PRINTER_NAME;
5875         }
5876
5877         *r->out.needed = 0;
5878         *r->out.server_major_version = 0;
5879         *r->out.server_minor_version = 0;
5880
5881         servername = get_server_name(printer);
5882
5883         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5884                 return WERR_BADFID;
5885         }
5886
5887         switch (r->in.level) {
5888         case 1:
5889                 result = construct_printer_driver_info_1(p->mem_ctx,
5890                                                          &r->out.info->info1,
5891                                                          snum,
5892                                                          servername,
5893                                                          r->in.architecture,
5894                                                          r->in.client_major_version);
5895                 break;
5896         case 2:
5897                 result = construct_printer_driver_info_2(p->mem_ctx,
5898                                                          &r->out.info->info2,
5899                                                          snum,
5900                                                          servername,
5901                                                          r->in.architecture,
5902                                                          r->in.client_major_version);
5903                 break;
5904         case 3:
5905                 result = construct_printer_driver_info_3(p->mem_ctx,
5906                                                          &r->out.info->info3,
5907                                                          snum,
5908                                                          servername,
5909                                                          r->in.architecture,
5910                                                          r->in.client_major_version);
5911                 break;
5912         case 6:
5913                 result = construct_printer_driver_info_6(p->mem_ctx,
5914                                                          &r->out.info->info6,
5915                                                          snum,
5916                                                          servername,
5917                                                          r->in.architecture,
5918                                                          r->in.client_major_version);
5919                 break;
5920         default:
5921 #if 0   /* JERRY */
5922         case 101:
5923                 /* apparently this call is the equivalent of
5924                    EnumPrinterDataEx() for the DsDriver key */
5925                 break;
5926 #endif
5927                 result = WERR_UNKNOWN_LEVEL;
5928                 break;
5929         }
5930
5931         if (!W_ERROR_IS_OK(result)) {
5932                 TALLOC_FREE(r->out.info);
5933                 return result;
5934         }
5935
5936         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5937                                                r->out.info, r->in.level);
5938         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5939
5940         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5941 }
5942
5943
5944 /****************************************************************
5945  _spoolss_StartPagePrinter
5946 ****************************************************************/
5947
5948 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5949                                  struct spoolss_StartPagePrinter *r)
5950 {
5951         POLICY_HND *handle = r->in.handle;
5952
5953         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5954
5955         if (!Printer) {
5956                 DEBUG(3,("_spoolss_StartPagePrinter: "
5957                         "Error in startpageprinter printer handle\n"));
5958                 return WERR_BADFID;
5959         }
5960
5961         Printer->page_started=True;
5962         return WERR_OK;
5963 }
5964
5965 /****************************************************************
5966  _spoolss_EndPagePrinter
5967 ****************************************************************/
5968
5969 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5970                                struct spoolss_EndPagePrinter *r)
5971 {
5972         POLICY_HND *handle = r->in.handle;
5973         int snum;
5974
5975         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5976
5977         if (!Printer) {
5978                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5979                         OUR_HANDLE(handle)));
5980                 return WERR_BADFID;
5981         }
5982
5983         if (!get_printer_snum(p, handle, &snum, NULL))
5984                 return WERR_BADFID;
5985
5986         Printer->page_started=False;
5987         print_job_endpage(snum, Printer->jobid);
5988
5989         return WERR_OK;
5990 }
5991
5992 /****************************************************************
5993  _spoolss_StartDocPrinter
5994 ****************************************************************/
5995
5996 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5997                                 struct spoolss_StartDocPrinter *r)
5998 {
5999         POLICY_HND *handle = r->in.handle;
6000         uint32_t *jobid = r->out.job_id;
6001         struct spoolss_DocumentInfo1 *info_1;
6002         int snum;
6003         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6004
6005         if (!Printer) {
6006                 DEBUG(2,("_spoolss_StartDocPrinter: "
6007                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6008                 return WERR_BADFID;
6009         }
6010
6011         if (r->in.level != 1) {
6012                 return WERR_UNKNOWN_LEVEL;
6013         }
6014
6015         info_1 = r->in.info.info1;
6016
6017         /*
6018          * a nice thing with NT is it doesn't listen to what you tell it.
6019          * when asked to send _only_ RAW datas, it tries to send datas
6020          * in EMF format.
6021          *
6022          * So I add checks like in NT Server ...
6023          */
6024
6025         if (info_1->datatype) {
6026                 if (strcmp(info_1->datatype, "RAW") != 0) {
6027                         (*jobid)=0;
6028                         return WERR_INVALID_DATATYPE;
6029                 }
6030         }
6031
6032         /* get the share number of the printer */
6033         if (!get_printer_snum(p, handle, &snum, NULL)) {
6034                 return WERR_BADFID;
6035         }
6036
6037         Printer->jobid = print_job_start(p->server_info, snum,
6038                                          info_1->document_name,
6039                                          Printer->nt_devmode);
6040
6041         /* An error occured in print_job_start() so return an appropriate
6042            NT error code. */
6043
6044         if (Printer->jobid == -1) {
6045                 return map_werror_from_unix(errno);
6046         }
6047
6048         Printer->document_started=True;
6049         (*jobid) = Printer->jobid;
6050
6051         return WERR_OK;
6052 }
6053
6054 /****************************************************************
6055  _spoolss_EndDocPrinter
6056 ****************************************************************/
6057
6058 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
6059                               struct spoolss_EndDocPrinter *r)
6060 {
6061         POLICY_HND *handle = r->in.handle;
6062
6063         return _spoolss_enddocprinter_internal(p, handle);
6064 }
6065
6066 /****************************************************************
6067  _spoolss_WritePrinter
6068 ****************************************************************/
6069
6070 WERROR _spoolss_WritePrinter(pipes_struct *p,
6071                              struct spoolss_WritePrinter *r)
6072 {
6073         POLICY_HND *handle = r->in.handle;
6074         uint32 buffer_size = r->in._data_size;
6075         uint8 *buffer = r->in.data.data;
6076         uint32 *buffer_written = &r->in._data_size;
6077         int snum;
6078         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6079
6080         if (!Printer) {
6081                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6082                         OUR_HANDLE(handle)));
6083                 *r->out.num_written = r->in._data_size;
6084                 return WERR_BADFID;
6085         }
6086
6087         if (!get_printer_snum(p, handle, &snum, NULL))
6088                 return WERR_BADFID;
6089
6090         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
6091                                         (SMB_OFF_T)-1, (size_t)buffer_size);
6092         if (*buffer_written == (uint32)-1) {
6093                 *r->out.num_written = 0;
6094                 if (errno == ENOSPC)
6095                         return WERR_NO_SPOOL_SPACE;
6096                 else
6097                         return WERR_ACCESS_DENIED;
6098         }
6099
6100         *r->out.num_written = r->in._data_size;
6101
6102         return WERR_OK;
6103 }
6104
6105 /********************************************************************
6106  * api_spoolss_getprinter
6107  * called from the spoolss dispatcher
6108  *
6109  ********************************************************************/
6110
6111 static WERROR control_printer(POLICY_HND *handle, uint32 command,
6112                               pipes_struct *p)
6113 {
6114         int snum;
6115         WERROR errcode = WERR_BADFUNC;
6116         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6117
6118         if (!Printer) {
6119                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6120                 return WERR_BADFID;
6121         }
6122
6123         if (!get_printer_snum(p, handle, &snum, NULL))
6124                 return WERR_BADFID;
6125
6126         switch (command) {
6127         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6128                 if (print_queue_pause(p->server_info, snum, &errcode)) {
6129                         errcode = WERR_OK;
6130                 }
6131                 break;
6132         case SPOOLSS_PRINTER_CONTROL_RESUME:
6133         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6134                 if (print_queue_resume(p->server_info, snum, &errcode)) {
6135                         errcode = WERR_OK;
6136                 }
6137                 break;
6138         case SPOOLSS_PRINTER_CONTROL_PURGE:
6139                 if (print_queue_purge(p->server_info, snum, &errcode)) {
6140                         errcode = WERR_OK;
6141                 }
6142                 break;
6143         default:
6144                 return WERR_UNKNOWN_LEVEL;
6145         }
6146
6147         return errcode;
6148 }
6149
6150
6151 /****************************************************************
6152  _spoolss_AbortPrinter
6153  * From MSDN: "Deletes printer's spool file if printer is configured
6154  * for spooling"
6155 ****************************************************************/
6156
6157 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6158                              struct spoolss_AbortPrinter *r)
6159 {
6160         POLICY_HND      *handle = r->in.handle;
6161         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6162         int             snum;
6163         WERROR          errcode = WERR_OK;
6164
6165         if (!Printer) {
6166                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6167                         OUR_HANDLE(handle)));
6168                 return WERR_BADFID;
6169         }
6170
6171         if (!get_printer_snum(p, handle, &snum, NULL))
6172                 return WERR_BADFID;
6173
6174         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6175
6176         return errcode;
6177 }
6178
6179 /********************************************************************
6180  * called by spoolss_api_setprinter
6181  * when updating a printer description
6182  ********************************************************************/
6183
6184 static WERROR update_printer_sec(POLICY_HND *handle,
6185                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6186 {
6187         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6188         WERROR result;
6189         int snum;
6190
6191         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6192
6193         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6194                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6195                          OUR_HANDLE(handle)));
6196
6197                 result = WERR_BADFID;
6198                 goto done;
6199         }
6200
6201         if (!secdesc_ctr) {
6202                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6203                 result = WERR_INVALID_PARAM;
6204                 goto done;
6205         }
6206
6207         /* Check the user has permissions to change the security
6208            descriptor.  By experimentation with two NT machines, the user
6209            requires Full Access to the printer to change security
6210            information. */
6211
6212         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6213                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6214                 result = WERR_ACCESS_DENIED;
6215                 goto done;
6216         }
6217
6218         /* NT seems to like setting the security descriptor even though
6219            nothing may have actually changed. */
6220
6221         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6222                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6223                 result = WERR_BADFID;
6224                 goto done;
6225         }
6226
6227         if (DEBUGLEVEL >= 10) {
6228                 SEC_ACL *the_acl;
6229                 int i;
6230
6231                 the_acl = old_secdesc_ctr->sd->dacl;
6232                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6233                            PRINTERNAME(snum), the_acl->num_aces));
6234
6235                 for (i = 0; i < the_acl->num_aces; i++) {
6236                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6237                                            &the_acl->aces[i].trustee),
6238                                   the_acl->aces[i].access_mask));
6239                 }
6240
6241                 the_acl = secdesc_ctr->sd->dacl;
6242
6243                 if (the_acl) {
6244                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6245                                    PRINTERNAME(snum), the_acl->num_aces));
6246
6247                         for (i = 0; i < the_acl->num_aces; i++) {
6248                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6249                                                    &the_acl->aces[i].trustee),
6250                                            the_acl->aces[i].access_mask));
6251                         }
6252                 } else {
6253                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6254                 }
6255         }
6256
6257         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6258         if (!new_secdesc_ctr) {
6259                 result = WERR_NOMEM;
6260                 goto done;
6261         }
6262
6263         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6264                 result = WERR_OK;
6265                 goto done;
6266         }
6267
6268         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6269
6270  done:
6271
6272         return result;
6273 }
6274
6275 /********************************************************************
6276  Canonicalize printer info from a client
6277
6278  ATTN: It does not matter what we set the servername to hear
6279  since we do the necessary work in get_a_printer() to set it to
6280  the correct value based on what the client sent in the
6281  _spoolss_open_printer_ex().
6282  ********************************************************************/
6283
6284 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6285 {
6286         fstring printername;
6287         const char *p;
6288
6289         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6290                 "portname=%s drivername=%s comment=%s location=%s\n",
6291                 info->servername, info->printername, info->sharename,
6292                 info->portname, info->drivername, info->comment, info->location));
6293
6294         /* we force some elements to "correct" values */
6295         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6296         fstrcpy(info->sharename, lp_servicename(snum));
6297
6298         /* check to see if we allow printername != sharename */
6299
6300         if ( lp_force_printername(snum) ) {
6301                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6302                         global_myname(), info->sharename );
6303         } else {
6304
6305                 /* make sure printername is in \\server\printername format */
6306
6307                 fstrcpy( printername, info->printername );
6308                 p = printername;
6309                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6310                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6311                                 p++;
6312                 }
6313
6314                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6315                          global_myname(), p );
6316         }
6317
6318         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6319         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6320
6321
6322
6323         return True;
6324 }
6325
6326 /****************************************************************************
6327 ****************************************************************************/
6328
6329 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6330 {
6331         char *cmd = lp_addport_cmd();
6332         char *command = NULL;
6333         int ret;
6334         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6335         bool is_print_op = False;
6336
6337         if ( !*cmd ) {
6338                 return WERR_ACCESS_DENIED;
6339         }
6340
6341         command = talloc_asprintf(ctx,
6342                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6343         if (!command) {
6344                 return WERR_NOMEM;
6345         }
6346
6347         if ( token )
6348                 is_print_op = user_has_privileges( token, &se_printop );
6349
6350         DEBUG(10,("Running [%s]\n", command));
6351
6352         /********* BEGIN SePrintOperatorPrivilege **********/
6353
6354         if ( is_print_op )
6355                 become_root();
6356
6357         ret = smbrun(command, NULL);
6358
6359         if ( is_print_op )
6360                 unbecome_root();
6361
6362         /********* END SePrintOperatorPrivilege **********/
6363
6364         DEBUGADD(10,("returned [%d]\n", ret));
6365
6366         TALLOC_FREE(command);
6367
6368         if ( ret != 0 ) {
6369                 return WERR_ACCESS_DENIED;
6370         }
6371
6372         return WERR_OK;
6373 }
6374
6375 /****************************************************************************
6376 ****************************************************************************/
6377
6378 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6379 {
6380         char *cmd = lp_addprinter_cmd();
6381         char **qlines;
6382         char *command = NULL;
6383         int numlines;
6384         int ret;
6385         int fd;
6386         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6387         bool is_print_op = False;
6388         char *remote_machine = talloc_strdup(ctx, "%m");
6389
6390         if (!remote_machine) {
6391                 return false;
6392         }
6393         remote_machine = talloc_sub_basic(ctx,
6394                                 current_user_info.smb_name,
6395                                 current_user_info.domain,
6396                                 remote_machine);
6397         if (!remote_machine) {
6398                 return false;
6399         }
6400
6401         command = talloc_asprintf(ctx,
6402                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6403                         cmd, printer->info_2->printername, printer->info_2->sharename,
6404                         printer->info_2->portname, printer->info_2->drivername,
6405                         printer->info_2->location, printer->info_2->comment, remote_machine);
6406         if (!command) {
6407                 return false;
6408         }
6409
6410         if ( token )
6411                 is_print_op = user_has_privileges( token, &se_printop );
6412
6413         DEBUG(10,("Running [%s]\n", command));
6414
6415         /********* BEGIN SePrintOperatorPrivilege **********/
6416
6417         if ( is_print_op )
6418                 become_root();
6419
6420         if ( (ret = smbrun(command, &fd)) == 0 ) {
6421                 /* Tell everyone we updated smb.conf. */
6422                 message_send_all(smbd_messaging_context(),
6423                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6424         }
6425
6426         if ( is_print_op )
6427                 unbecome_root();
6428
6429         /********* END SePrintOperatorPrivilege **********/
6430
6431         DEBUGADD(10,("returned [%d]\n", ret));
6432
6433         TALLOC_FREE(command);
6434         TALLOC_FREE(remote_machine);
6435
6436         if ( ret != 0 ) {
6437                 if (fd != -1)
6438                         close(fd);
6439                 return False;
6440         }
6441
6442         /* reload our services immediately */
6443         reload_services( False );
6444
6445         numlines = 0;
6446         /* Get lines and convert them back to dos-codepage */
6447         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6448         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6449         close(fd);
6450
6451         /* Set the portname to what the script says the portname should be. */
6452         /* but don't require anything to be return from the script exit a good error code */
6453
6454         if (numlines) {
6455                 /* Set the portname to what the script says the portname should be. */
6456                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6457                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6458         }
6459
6460         TALLOC_FREE(qlines);
6461         return True;
6462 }
6463
6464
6465 /********************************************************************
6466  * Called by spoolss_api_setprinter
6467  * when updating a printer description.
6468  ********************************************************************/
6469
6470 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6471                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6472                              struct spoolss_DeviceMode *devmode)
6473 {
6474         int snum;
6475         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6476         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6477         WERROR result;
6478         UNISTR2 buffer;
6479         fstring asc_buffer;
6480
6481         DEBUG(8,("update_printer\n"));
6482
6483         result = WERR_OK;
6484
6485         if (!Printer) {
6486                 result = WERR_BADFID;
6487                 goto done;
6488         }
6489
6490         if (!get_printer_snum(p, handle, &snum, NULL)) {
6491                 result = WERR_BADFID;
6492                 goto done;
6493         }
6494
6495         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6496             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6497                 result = WERR_BADFID;
6498                 goto done;
6499         }
6500
6501         DEBUGADD(8,("Converting info_2 struct\n"));
6502
6503         /*
6504          * convert_printer_info converts the incoming
6505          * info from the client and overwrites the info
6506          * just read from the tdb in the pointer 'printer'.
6507          */
6508
6509         if (!convert_printer_info_new(info_ctr, printer)) {
6510                 result =  WERR_NOMEM;
6511                 goto done;
6512         }
6513
6514         if (devmode) {
6515                 /* we have a valid devmode
6516                    convert it and link it*/
6517
6518                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6519                 if (!convert_devicemode_new(printer->info_2->printername,
6520                                             devmode,
6521                                             &printer->info_2->devmode)) {
6522                         result =  WERR_NOMEM;
6523                         goto done;
6524                 }
6525         }
6526
6527         /* Do sanity check on the requested changes for Samba */
6528
6529         if (!check_printer_ok(printer->info_2, snum)) {
6530                 result = WERR_INVALID_PARAM;
6531                 goto done;
6532         }
6533
6534         /* FIXME!!! If the driver has changed we really should verify that
6535            it is installed before doing much else   --jerry */
6536
6537         /* Check calling user has permission to update printer description */
6538
6539         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6540                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6541                 result = WERR_ACCESS_DENIED;
6542                 goto done;
6543         }
6544
6545         /* Call addprinter hook */
6546         /* Check changes to see if this is really needed */
6547
6548         if ( *lp_addprinter_cmd()
6549                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6550                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6551                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6552                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6553         {
6554                 /* add_printer_hook() will call reload_services() */
6555
6556                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6557                                        printer) ) {
6558                         result = WERR_ACCESS_DENIED;
6559                         goto done;
6560                 }
6561         }
6562
6563         /*
6564          * When a *new* driver is bound to a printer, the drivername is used to
6565          * lookup previously saved driver initialization info, which is then
6566          * bound to the printer, simulating what happens in the Windows arch.
6567          */
6568         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6569         {
6570                 if (!set_driver_init(printer, 2))
6571                 {
6572                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6573                                 printer->info_2->drivername));
6574                 }
6575
6576                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6577                         printer->info_2->drivername));
6578
6579                 notify_printer_driver(snum, printer->info_2->drivername);
6580         }
6581
6582         /*
6583          * flag which changes actually occured.  This is a small subset of
6584          * all the possible changes.  We also have to update things in the
6585          * DsSpooler key.
6586          */
6587
6588         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6589                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6590                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6591                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6592
6593                 notify_printer_comment(snum, printer->info_2->comment);
6594         }
6595
6596         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6597                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6598                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6599                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6600
6601                 notify_printer_sharename(snum, printer->info_2->sharename);
6602         }
6603
6604         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6605                 char *pname;
6606
6607                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6608                         pname++;
6609                 else
6610                         pname = printer->info_2->printername;
6611
6612
6613                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6614                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6615                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6616
6617                 notify_printer_printername( snum, pname );
6618         }
6619
6620         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6621                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6622                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6623                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6624
6625                 notify_printer_port(snum, printer->info_2->portname);
6626         }
6627
6628         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6629                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6630                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6631                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6632
6633                 notify_printer_location(snum, printer->info_2->location);
6634         }
6635
6636         /* here we need to update some more DsSpooler keys */
6637         /* uNCName, serverName, shortServerName */
6638
6639         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6640         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6641                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6642         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6643                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6644
6645         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6646                  global_myname(), printer->info_2->sharename );
6647         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6648         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6649                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6650
6651         /* Update printer info */
6652         result = mod_a_printer(printer, 2);
6653
6654 done:
6655         free_a_printer(&printer, 2);
6656         free_a_printer(&old_printer, 2);
6657
6658
6659         return result;
6660 }
6661
6662 /****************************************************************************
6663 ****************************************************************************/
6664 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6665                                            struct spoolss_SetPrinterInfo7 *info7)
6666 {
6667 #ifdef HAVE_ADS
6668         int snum;
6669         Printer_entry *Printer;
6670
6671         if ( lp_security() != SEC_ADS ) {
6672                 return WERR_UNKNOWN_LEVEL;
6673         }
6674
6675         Printer = find_printer_index_by_hnd(p, handle);
6676
6677         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6678
6679         if (!Printer)
6680                 return WERR_BADFID;
6681
6682         if (!get_printer_snum(p, handle, &snum, NULL))
6683                 return WERR_BADFID;
6684
6685         nt_printer_publish(Printer, snum, info7->action);
6686
6687         return WERR_OK;
6688 #else
6689         return WERR_UNKNOWN_LEVEL;
6690 #endif
6691 }
6692
6693 /****************************************************************
6694  _spoolss_SetPrinter
6695 ****************************************************************/
6696
6697 WERROR _spoolss_SetPrinter(pipes_struct *p,
6698                            struct spoolss_SetPrinter *r)
6699 {
6700         POLICY_HND *handle = r->in.handle;
6701         WERROR result;
6702
6703         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6704
6705         if (!Printer) {
6706                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6707                         OUR_HANDLE(handle)));
6708                 return WERR_BADFID;
6709         }
6710
6711         /* check the level */
6712         switch (r->in.info_ctr->level) {
6713                 case 0:
6714                         return control_printer(handle, r->in.command, p);
6715                 case 2:
6716                         result = update_printer(p, handle,
6717                                                 r->in.info_ctr,
6718                                                 r->in.devmode_ctr->devmode);
6719                         if (!W_ERROR_IS_OK(result))
6720                                 return result;
6721                         if (r->in.secdesc_ctr->sd)
6722                                 result = update_printer_sec(handle, p,
6723                                                             r->in.secdesc_ctr);
6724                         return result;
6725                 case 3:
6726                         return update_printer_sec(handle, p,
6727                                                   r->in.secdesc_ctr);
6728                 case 7:
6729                         return publish_or_unpublish_printer(p, handle,
6730                                                             r->in.info_ctr->info.info7);
6731                 default:
6732                         return WERR_UNKNOWN_LEVEL;
6733         }
6734 }
6735
6736 /****************************************************************
6737  _spoolss_FindClosePrinterNotify
6738 ****************************************************************/
6739
6740 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6741                                        struct spoolss_FindClosePrinterNotify *r)
6742 {
6743         POLICY_HND *handle = r->in.handle;
6744         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6745
6746         if (!Printer) {
6747                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6748                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6749                 return WERR_BADFID;
6750         }
6751
6752         if (Printer->notify.client_connected==True) {
6753                 int snum = -1;
6754
6755                 if ( Printer->printer_type == SPLHND_SERVER)
6756                         snum = -1;
6757                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6758                                 !get_printer_snum(p, handle, &snum, NULL) )
6759                         return WERR_BADFID;
6760
6761                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6762         }
6763
6764         Printer->notify.flags=0;
6765         Printer->notify.options=0;
6766         Printer->notify.localmachine[0]='\0';
6767         Printer->notify.printerlocal=0;
6768         TALLOC_FREE(Printer->notify.option);
6769         Printer->notify.client_connected=False;
6770
6771         return WERR_OK;
6772 }
6773
6774 /****************************************************************
6775  _spoolss_AddJob
6776 ****************************************************************/
6777
6778 WERROR _spoolss_AddJob(pipes_struct *p,
6779                        struct spoolss_AddJob *r)
6780 {
6781         if (!r->in.buffer && (r->in.offered != 0)) {
6782                 return WERR_INVALID_PARAM;
6783         }
6784
6785         /* this is what a NT server returns for AddJob. AddJob must fail on
6786          * non-local printers */
6787
6788         if (r->in.level != 1) {
6789                 return WERR_UNKNOWN_LEVEL;
6790         }
6791
6792         return WERR_INVALID_PARAM;
6793 }
6794
6795 /****************************************************************************
6796 fill_job_info1
6797 ****************************************************************************/
6798
6799 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6800                              struct spoolss_JobInfo1 *r,
6801                              const print_queue_struct *queue,
6802                              int position, int snum,
6803                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6804 {
6805         struct tm *t;
6806
6807         t = gmtime(&queue->time);
6808
6809         r->job_id               = queue->job;
6810
6811         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6812         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6813         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6814         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6815         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6816         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6817         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6818         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6819         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6820         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6821         r->text_status          = talloc_strdup(mem_ctx, "");
6822         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6823
6824         r->status               = nt_printj_status(queue->status);
6825         r->priority             = queue->priority;
6826         r->position             = position;
6827         r->total_pages          = queue->page_count;
6828         r->pages_printed        = 0; /* ??? */
6829
6830         init_systemtime(&r->submitted, t);
6831
6832         return WERR_OK;
6833 }
6834
6835 /****************************************************************************
6836 fill_job_info2
6837 ****************************************************************************/
6838
6839 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6840                              struct spoolss_JobInfo2 *r,
6841                              const print_queue_struct *queue,
6842                              int position, int snum,
6843                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6844                              struct spoolss_DeviceMode *devmode)
6845 {
6846         struct tm *t;
6847
6848         t = gmtime(&queue->time);
6849
6850         r->job_id               = queue->job;
6851
6852         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6853         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6854         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6855         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6856         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6857         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6858         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6859         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6860         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6861         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6862         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6863         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6864         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6865         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6866         r->parameters           = talloc_strdup(mem_ctx, "");
6867         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6868         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6869         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6870
6871         r->devmode              = devmode;
6872
6873         r->text_status          = talloc_strdup(mem_ctx, "");
6874         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6875
6876         r->secdesc              = NULL;
6877
6878         r->status               = nt_printj_status(queue->status);
6879         r->priority             = queue->priority;
6880         r->position             = position;
6881         r->start_time           = 0;
6882         r->until_time           = 0;
6883         r->total_pages          = queue->page_count;
6884         r->size                 = queue->size;
6885         init_systemtime(&r->submitted, t);
6886         r->time                 = 0;
6887         r->pages_printed        = 0; /* ??? */
6888
6889         return WERR_OK;
6890 }
6891
6892 /****************************************************************************
6893  Enumjobs at level 1.
6894 ****************************************************************************/
6895
6896 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6897                               const print_queue_struct *queue,
6898                               uint32_t num_queues, int snum,
6899                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6900                               union spoolss_JobInfo **info_p,
6901                               uint32_t *count)
6902 {
6903         union spoolss_JobInfo *info;
6904         int i;
6905         WERROR result = WERR_OK;
6906
6907         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6908         W_ERROR_HAVE_NO_MEMORY(info);
6909
6910         *count = num_queues;
6911
6912         for (i=0; i<*count; i++) {
6913                 result = fill_job_info1(info,
6914                                         &info[i].info1,
6915                                         &queue[i],
6916                                         i,
6917                                         snum,
6918                                         ntprinter);
6919                 if (!W_ERROR_IS_OK(result)) {
6920                         goto out;
6921                 }
6922         }
6923
6924  out:
6925         if (!W_ERROR_IS_OK(result)) {
6926                 TALLOC_FREE(info);
6927                 *count = 0;
6928                 return result;
6929         }
6930
6931         *info_p = info;
6932
6933         return WERR_OK;
6934 }
6935
6936 /****************************************************************************
6937  Enumjobs at level 2.
6938 ****************************************************************************/
6939
6940 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6941                               const print_queue_struct *queue,
6942                               uint32_t num_queues, int snum,
6943                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6944                               union spoolss_JobInfo **info_p,
6945                               uint32_t *count)
6946 {
6947         union spoolss_JobInfo *info;
6948         int i;
6949         WERROR result = WERR_OK;
6950
6951         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6952         W_ERROR_HAVE_NO_MEMORY(info);
6953
6954         *count = num_queues;
6955
6956         for (i=0; i<*count; i++) {
6957
6958                 struct spoolss_DeviceMode *devmode;
6959
6960                 devmode = construct_dev_mode_new(info, lp_const_servicename(snum));
6961                 if (!devmode) {
6962                         result = WERR_NOMEM;
6963                         goto out;
6964                 }
6965
6966                 result = fill_job_info2(info,
6967                                         &info[i].info2,
6968                                         &queue[i],
6969                                         i,
6970                                         snum,
6971                                         ntprinter,
6972                                         devmode);
6973                 if (!W_ERROR_IS_OK(result)) {
6974                         goto out;
6975                 }
6976         }
6977
6978  out:
6979         if (!W_ERROR_IS_OK(result)) {
6980                 TALLOC_FREE(info);
6981                 *count = 0;
6982                 return result;
6983         }
6984
6985         *info_p = info;
6986
6987         return WERR_OK;
6988 }
6989
6990 /****************************************************************
6991  _spoolss_EnumJobs
6992 ****************************************************************/
6993
6994 WERROR _spoolss_EnumJobs(pipes_struct *p,
6995                          struct spoolss_EnumJobs *r)
6996 {
6997         WERROR result;
6998         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6999         int snum;
7000         print_status_struct prt_status;
7001         print_queue_struct *queue = NULL;
7002         uint32_t count;
7003
7004         /* that's an [in out] buffer */
7005
7006         if (!r->in.buffer && (r->in.offered != 0)) {
7007                 return WERR_INVALID_PARAM;
7008         }
7009
7010         DEBUG(4,("_spoolss_EnumJobs\n"));
7011
7012         *r->out.needed = 0;
7013         *r->out.count = 0;
7014         *r->out.info = NULL;
7015
7016         /* lookup the printer snum and tdb entry */
7017
7018         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7019                 return WERR_BADFID;
7020         }
7021
7022         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
7023         if (!W_ERROR_IS_OK(result)) {
7024                 return result;
7025         }
7026
7027         count = print_queue_status(snum, &queue, &prt_status);
7028         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7029                 count, prt_status.status, prt_status.message));
7030
7031         if (count == 0) {
7032                 SAFE_FREE(queue);
7033                 free_a_printer(&ntprinter, 2);
7034                 return WERR_OK;
7035         }
7036
7037         switch (r->in.level) {
7038         case 1:
7039                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7040                                          ntprinter, r->out.info, r->out.count);
7041                 break;
7042         case 2:
7043                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7044                                          ntprinter, r->out.info, r->out.count);
7045                 break;
7046         default:
7047                 result = WERR_UNKNOWN_LEVEL;
7048                 break;
7049         }
7050
7051         SAFE_FREE(queue);
7052         free_a_printer(&ntprinter, 2);
7053
7054         if (!W_ERROR_IS_OK(result)) {
7055                 return result;
7056         }
7057
7058         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7059                                                      spoolss_EnumJobs, NULL,
7060                                                      *r->out.info, r->in.level,
7061                                                      *r->out.count);
7062         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7063         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7064
7065         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7066 }
7067
7068 /****************************************************************
7069  _spoolss_ScheduleJob
7070 ****************************************************************/
7071
7072 WERROR _spoolss_ScheduleJob(pipes_struct *p,
7073                             struct spoolss_ScheduleJob *r)
7074 {
7075         return WERR_OK;
7076 }
7077
7078 /****************************************************************
7079  _spoolss_SetJob
7080 ****************************************************************/
7081
7082 WERROR _spoolss_SetJob(pipes_struct *p,
7083                        struct spoolss_SetJob *r)
7084 {
7085         POLICY_HND *handle = r->in.handle;
7086         uint32 jobid = r->in.job_id;
7087         uint32 command = r->in.command;
7088
7089         int snum;
7090         WERROR errcode = WERR_BADFUNC;
7091
7092         if (!get_printer_snum(p, handle, &snum, NULL)) {
7093                 return WERR_BADFID;
7094         }
7095
7096         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
7097                 return WERR_INVALID_PRINTER_NAME;
7098         }
7099
7100         switch (command) {
7101         case SPOOLSS_JOB_CONTROL_CANCEL:
7102         case SPOOLSS_JOB_CONTROL_DELETE:
7103                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
7104                         errcode = WERR_OK;
7105                 }
7106                 break;
7107         case SPOOLSS_JOB_CONTROL_PAUSE:
7108                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
7109                         errcode = WERR_OK;
7110                 }
7111                 break;
7112         case SPOOLSS_JOB_CONTROL_RESTART:
7113         case SPOOLSS_JOB_CONTROL_RESUME:
7114                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
7115                         errcode = WERR_OK;
7116                 }
7117                 break;
7118         default:
7119                 return WERR_UNKNOWN_LEVEL;
7120         }
7121
7122         return errcode;
7123 }
7124
7125 /****************************************************************************
7126  Enumerates all printer drivers at level 1.
7127 ****************************************************************************/
7128
7129 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
7130                                         const char *servername,
7131                                         const char *architecture,
7132                                         union spoolss_DriverInfo **info_p,
7133                                         uint32_t *count)
7134 {
7135         int i;
7136         int ndrivers;
7137         uint32_t version;
7138         fstring *list = NULL;
7139         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7140         union spoolss_DriverInfo *info = NULL;
7141         WERROR result = WERR_OK;
7142
7143         *count = 0;
7144
7145         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7146                 list = NULL;
7147                 ndrivers = get_ntdrivers(&list, architecture, version);
7148                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
7149                         ndrivers, architecture, version));
7150
7151                 if (ndrivers == -1) {
7152                         result = WERR_NOMEM;
7153                         goto out;
7154                 }
7155
7156                 if (ndrivers != 0) {
7157                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7158                                                     union spoolss_DriverInfo,
7159                                                     *count + ndrivers);
7160                         if (!info) {
7161                                 DEBUG(0,("enumprinterdrivers_level1: "
7162                                         "failed to enlarge driver info buffer!\n"));
7163                                 result = WERR_NOMEM;
7164                                 goto out;
7165                         }
7166                 }
7167
7168                 for (i=0; i<ndrivers; i++) {
7169                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7170                         ZERO_STRUCT(driver);
7171                         result = get_a_printer_driver(&driver, 3, list[i],
7172                                                       architecture, version);
7173                         if (!W_ERROR_IS_OK(result)) {
7174                                 goto out;
7175                         }
7176                         result = fill_printer_driver_info1(info, &info[*count+i].info1,
7177                                                            &driver, servername,
7178                                                            architecture);
7179                         if (!W_ERROR_IS_OK(result)) {
7180                                 free_a_printer_driver(driver, 3);
7181                                 goto out;
7182                         }
7183                         free_a_printer_driver(driver, 3);
7184                 }
7185
7186                 *count += ndrivers;
7187                 SAFE_FREE(list);
7188         }
7189
7190  out:
7191         SAFE_FREE(list);
7192
7193         if (!W_ERROR_IS_OK(result)) {
7194                 TALLOC_FREE(info);
7195                 *count = 0;
7196                 return result;
7197         }
7198
7199         *info_p = info;
7200
7201         return WERR_OK;
7202 }
7203
7204 /****************************************************************************
7205  Enumerates all printer drivers at level 2.
7206 ****************************************************************************/
7207
7208 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
7209                                         const char *servername,
7210                                         const char *architecture,
7211                                         union spoolss_DriverInfo **info_p,
7212                                         uint32_t *count)
7213 {
7214         int i;
7215         int ndrivers;
7216         uint32_t version;
7217         fstring *list = NULL;
7218         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7219         union spoolss_DriverInfo *info = NULL;
7220         WERROR result = WERR_OK;
7221
7222         *count = 0;
7223
7224         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7225                 list = NULL;
7226                 ndrivers = get_ntdrivers(&list, architecture, version);
7227                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
7228                         ndrivers, architecture, version));
7229
7230                 if (ndrivers == -1) {
7231                         result = WERR_NOMEM;
7232                         goto out;
7233                 }
7234
7235                 if (ndrivers != 0) {
7236                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7237                                                     union spoolss_DriverInfo,
7238                                                     *count + ndrivers);
7239                         if (!info) {
7240                                 DEBUG(0,("enumprinterdrivers_level2: "
7241                                         "failed to enlarge driver info buffer!\n"));
7242                                 result = WERR_NOMEM;
7243                                 goto out;
7244                         }
7245                 }
7246
7247                 for (i=0; i<ndrivers; i++) {
7248                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7249                         ZERO_STRUCT(driver);
7250                         result = get_a_printer_driver(&driver, 3, list[i],
7251                                                       architecture, version);
7252                         if (!W_ERROR_IS_OK(result)) {
7253                                 goto out;
7254                         }
7255                         result = fill_printer_driver_info2(info, &info[*count+i].info2,
7256                                                            &driver, servername);
7257                         if (!W_ERROR_IS_OK(result)) {
7258                                 free_a_printer_driver(driver, 3);
7259                                 goto out;
7260                         }
7261                         free_a_printer_driver(driver, 3);
7262                 }
7263
7264                 *count += ndrivers;
7265                 SAFE_FREE(list);
7266         }
7267
7268  out:
7269         SAFE_FREE(list);
7270
7271         if (!W_ERROR_IS_OK(result)) {
7272                 TALLOC_FREE(info);
7273                 *count = 0;
7274                 return result;
7275         }
7276
7277         *info_p = info;
7278
7279         return WERR_OK;
7280 }
7281
7282 /****************************************************************************
7283  Enumerates all printer drivers at level 3.
7284 ****************************************************************************/
7285
7286 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
7287                                         const char *servername,
7288                                         const char *architecture,
7289                                         union spoolss_DriverInfo **info_p,
7290                                         uint32_t *count)
7291 {
7292         int i;
7293         int ndrivers;
7294         uint32_t version;
7295         fstring *list = NULL;
7296         union spoolss_DriverInfo *info = NULL;
7297         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7298         WERROR result = WERR_OK;
7299
7300         *count = 0;
7301
7302         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7303                 list = NULL;
7304                 ndrivers = get_ntdrivers(&list, architecture, version);
7305                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
7306                         ndrivers, architecture, version));
7307
7308                 if (ndrivers == -1) {
7309                         result = WERR_NOMEM;
7310                         goto out;
7311                 }
7312
7313                 if (ndrivers != 0) {
7314                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7315                                                     union spoolss_DriverInfo,
7316                                                     *count + ndrivers);
7317                         if (!info) {
7318                                 DEBUG(0,("enumprinterdrivers_level3: "
7319                                         "failed to enlarge driver info buffer!\n"));
7320                                 result = WERR_NOMEM;
7321                                 goto out;
7322                         }
7323                 }
7324
7325                 for (i=0; i<ndrivers; i++) {
7326                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7327                         ZERO_STRUCT(driver);
7328                         result = get_a_printer_driver(&driver, 3, list[i],
7329                                                       architecture, version);
7330                         if (!W_ERROR_IS_OK(result)) {
7331                                 goto out;
7332                         }
7333                         result = fill_printer_driver_info3(info, &info[*count+i].info3,
7334                                                            &driver, servername);
7335                         if (!W_ERROR_IS_OK(result)) {
7336                                 free_a_printer_driver(driver, 3);
7337                                 goto out;
7338                         }
7339
7340                         free_a_printer_driver(driver, 3);
7341                 }
7342
7343                 *count += ndrivers;
7344                 SAFE_FREE(list);
7345         }
7346
7347  out:
7348         SAFE_FREE(list);
7349
7350         if (!W_ERROR_IS_OK(result)) {
7351                 TALLOC_FREE(info);
7352                 *count = 0;
7353                 return result;
7354         }
7355
7356         *info_p = info;
7357
7358         return WERR_OK;
7359 }
7360
7361 /****************************************************************
7362  _spoolss_EnumPrinterDrivers
7363 ****************************************************************/
7364
7365 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
7366                                    struct spoolss_EnumPrinterDrivers *r)
7367 {
7368         const char *cservername;
7369         WERROR result;
7370
7371         /* that's an [in out] buffer */
7372
7373         if (!r->in.buffer && (r->in.offered != 0)) {
7374                 return WERR_INVALID_PARAM;
7375         }
7376
7377         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7378
7379         *r->out.needed = 0;
7380         *r->out.count = 0;
7381         *r->out.info = NULL;
7382
7383         cservername = canon_servername(r->in.server);
7384
7385         if (!is_myname_or_ipaddr(cservername)) {
7386                 return WERR_UNKNOWN_PRINTER_DRIVER;
7387         }
7388
7389         switch (r->in.level) {
7390         case 1:
7391                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
7392                                                    r->in.environment,
7393                                                    r->out.info, r->out.count);
7394                 break;
7395         case 2:
7396                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
7397                                                    r->in.environment,
7398                                                    r->out.info, r->out.count);
7399                 break;
7400         case 3:
7401                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
7402                                                    r->in.environment,
7403                                                    r->out.info, r->out.count);
7404                 break;
7405         default:
7406                 return WERR_UNKNOWN_LEVEL;
7407         }
7408
7409         if (!W_ERROR_IS_OK(result)) {
7410                 return result;
7411         }
7412
7413         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7414                                                      spoolss_EnumPrinterDrivers, NULL,
7415                                                      *r->out.info, r->in.level,
7416                                                      *r->out.count);
7417         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7418         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7419
7420         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7421 }
7422
7423 /****************************************************************************
7424 ****************************************************************************/
7425
7426 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7427                                struct spoolss_FormInfo1 *r,
7428                                const nt_forms_struct *form)
7429 {
7430         r->form_name    = talloc_strdup(mem_ctx, form->name);
7431         W_ERROR_HAVE_NO_MEMORY(r->form_name);
7432
7433         r->flags        = form->flag;
7434         r->size.width   = form->width;
7435         r->size.height  = form->length;
7436         r->area.left    = form->left;
7437         r->area.top     = form->top;
7438         r->area.right   = form->right;
7439         r->area.bottom  = form->bottom;
7440
7441         return WERR_OK;
7442 }
7443
7444 /****************************************************************
7445  spoolss_enumforms_level1
7446 ****************************************************************/
7447
7448 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7449                                        const nt_forms_struct *builtin_forms,
7450                                        uint32_t num_builtin_forms,
7451                                        const nt_forms_struct *user_forms,
7452                                        uint32_t num_user_forms,
7453                                        union spoolss_FormInfo **info_p,
7454                                        uint32_t *count)
7455 {
7456         union spoolss_FormInfo *info;
7457         WERROR result = WERR_OK;
7458         int i;
7459
7460         *count = num_builtin_forms + num_user_forms;
7461
7462         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7463         W_ERROR_HAVE_NO_MEMORY(info);
7464
7465         /* construct the list of form structures */
7466         for (i=0; i<num_builtin_forms; i++) {
7467                 DEBUGADD(6,("Filling form number [%d]\n",i));
7468                 result = fill_form_info_1(info, &info[i].info1,
7469                                           &builtin_forms[i]);
7470                 if (!W_ERROR_IS_OK(result)) {
7471                         goto out;
7472                 }
7473         }
7474
7475         for (; i<num_user_forms; i++) {
7476                 DEBUGADD(6,("Filling form number [%d]\n",i));
7477                 result = fill_form_info_1(info, &info[i].info1,
7478                                           &user_forms[i-num_builtin_forms]);
7479                 if (!W_ERROR_IS_OK(result)) {
7480                         goto out;
7481                 }
7482         }
7483
7484  out:
7485         if (!W_ERROR_IS_OK(result)) {
7486                 TALLOC_FREE(info);
7487                 *count = 0;
7488                 return result;
7489         }
7490
7491         *info_p = info;
7492
7493         return WERR_OK;
7494 }
7495
7496 /****************************************************************
7497  _spoolss_EnumForms
7498 ****************************************************************/
7499
7500 WERROR _spoolss_EnumForms(pipes_struct *p,
7501                           struct spoolss_EnumForms *r)
7502 {
7503         WERROR result;
7504         nt_forms_struct *user_forms = NULL;
7505         nt_forms_struct *builtin_forms = NULL;
7506         uint32_t num_user_forms;
7507         uint32_t num_builtin_forms;
7508
7509         *r->out.count = 0;
7510         *r->out.needed = 0;
7511         *r->out.info = NULL;
7512
7513         /* that's an [in out] buffer */
7514
7515         if (!r->in.buffer && (r->in.offered != 0) ) {
7516                 return WERR_INVALID_PARAM;
7517         }
7518
7519         DEBUG(4,("_spoolss_EnumForms\n"));
7520         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7521         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7522
7523         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7524         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7525         num_user_forms = get_ntforms(&user_forms);
7526         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7527
7528         if (num_user_forms + num_builtin_forms == 0) {
7529                 SAFE_FREE(builtin_forms);
7530                 SAFE_FREE(user_forms);
7531                 return WERR_NO_MORE_ITEMS;
7532         }
7533
7534         switch (r->in.level) {
7535         case 1:
7536                 result = spoolss_enumforms_level1(p->mem_ctx,
7537                                                   builtin_forms,
7538                                                   num_builtin_forms,
7539                                                   user_forms,
7540                                                   num_user_forms,
7541                                                   r->out.info,
7542                                                   r->out.count);
7543                 break;
7544         default:
7545                 result = WERR_UNKNOWN_LEVEL;
7546                 break;
7547         }
7548
7549         SAFE_FREE(user_forms);
7550         SAFE_FREE(builtin_forms);
7551
7552         if (!W_ERROR_IS_OK(result)) {
7553                 return result;
7554         }
7555
7556         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7557                                                      spoolss_EnumForms, NULL,
7558                                                      *r->out.info, r->in.level,
7559                                                      *r->out.count);
7560         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7561         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7562
7563         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7564 }
7565
7566 /****************************************************************
7567 ****************************************************************/
7568
7569 static WERROR find_form_byname(const char *name,
7570                                nt_forms_struct *form)
7571 {
7572         nt_forms_struct *list = NULL;
7573         int num_forms = 0, i = 0;
7574
7575         if (get_a_builtin_ntform_by_string(name, form)) {
7576                 return WERR_OK;
7577         }
7578
7579         num_forms = get_ntforms(&list);
7580         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7581
7582         if (num_forms == 0) {
7583                 return WERR_BADFID;
7584         }
7585
7586         /* Check if the requested name is in the list of form structures */
7587         for (i = 0; i < num_forms; i++) {
7588
7589                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7590
7591                 if (strequal(name, list[i].name)) {
7592                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7593                         *form = list[i];
7594                         SAFE_FREE(list);
7595                         return WERR_OK;
7596                 }
7597         }
7598
7599         SAFE_FREE(list);
7600
7601         return WERR_BADFID;
7602 }
7603
7604 /****************************************************************
7605  _spoolss_GetForm
7606 ****************************************************************/
7607
7608 WERROR _spoolss_GetForm(pipes_struct *p,
7609                         struct spoolss_GetForm *r)
7610 {
7611         WERROR result;
7612         nt_forms_struct form;
7613
7614         /* that's an [in out] buffer */
7615
7616         if (!r->in.buffer && (r->in.offered != 0)) {
7617                 return WERR_INVALID_PARAM;
7618         }
7619
7620         DEBUG(4,("_spoolss_GetForm\n"));
7621         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7622         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7623
7624         result = find_form_byname(r->in.form_name, &form);
7625         if (!W_ERROR_IS_OK(result)) {
7626                 TALLOC_FREE(r->out.info);
7627                 return result;
7628         }
7629
7630         switch (r->in.level) {
7631         case 1:
7632                 result = fill_form_info_1(p->mem_ctx,
7633                                           &r->out.info->info1,
7634                                           &form);
7635                 break;
7636
7637         default:
7638                 result = WERR_UNKNOWN_LEVEL;
7639                 break;
7640         }
7641
7642         if (!W_ERROR_IS_OK(result)) {
7643                 TALLOC_FREE(r->out.info);
7644                 return result;
7645         }
7646
7647         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7648                                                r->out.info, r->in.level);
7649         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7650
7651         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7652 }
7653
7654 /****************************************************************************
7655 ****************************************************************************/
7656
7657 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7658                           struct spoolss_PortInfo1 *r,
7659                           const char *name)
7660 {
7661         r->port_name = talloc_strdup(mem_ctx, name);
7662         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7663
7664         return WERR_OK;
7665 }
7666
7667 /****************************************************************************
7668  TODO: This probably needs distinguish between TCP/IP and Local ports
7669  somehow.
7670 ****************************************************************************/
7671
7672 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7673                           struct spoolss_PortInfo2 *r,
7674                           const char *name)
7675 {
7676         r->port_name = talloc_strdup(mem_ctx, name);
7677         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7678
7679         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7680         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7681
7682         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7683         W_ERROR_HAVE_NO_MEMORY(r->description);
7684
7685         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7686         r->reserved = 0;
7687
7688         return WERR_OK;
7689 }
7690
7691
7692 /****************************************************************************
7693  wrapper around the enumer ports command
7694 ****************************************************************************/
7695
7696 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7697 {
7698         char *cmd = lp_enumports_cmd();
7699         char **qlines = NULL;
7700         char *command = NULL;
7701         int numlines;
7702         int ret;
7703         int fd;
7704
7705         *count = 0;
7706         *lines = NULL;
7707
7708         /* if no hook then just fill in the default port */
7709
7710         if ( !*cmd ) {
7711                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7712                         return WERR_NOMEM;
7713                 }
7714                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7715                         TALLOC_FREE(qlines);
7716                         return WERR_NOMEM;
7717                 }
7718                 qlines[1] = NULL;
7719                 numlines = 1;
7720         }
7721         else {
7722                 /* we have a valid enumport command */
7723
7724                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7725                 if (!command) {
7726                         return WERR_NOMEM;
7727                 }
7728
7729                 DEBUG(10,("Running [%s]\n", command));
7730                 ret = smbrun(command, &fd);
7731                 DEBUG(10,("Returned [%d]\n", ret));
7732                 TALLOC_FREE(command);
7733                 if (ret != 0) {
7734                         if (fd != -1) {
7735                                 close(fd);
7736                         }
7737                         return WERR_ACCESS_DENIED;
7738                 }
7739
7740                 numlines = 0;
7741                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7742                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7743                 close(fd);
7744         }
7745
7746         *count = numlines;
7747         *lines = qlines;
7748
7749         return WERR_OK;
7750 }
7751
7752 /****************************************************************************
7753  enumports level 1.
7754 ****************************************************************************/
7755
7756 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7757                                 union spoolss_PortInfo **info_p,
7758                                 uint32_t *count)
7759 {
7760         union spoolss_PortInfo *info = NULL;
7761         int i=0;
7762         WERROR result = WERR_OK;
7763         char **qlines = NULL;
7764         int numlines = 0;
7765
7766         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7767         if (!W_ERROR_IS_OK(result)) {
7768                 goto out;
7769         }
7770
7771         if (numlines) {
7772                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7773                 if (!info) {
7774                         DEBUG(10,("Returning WERR_NOMEM\n"));
7775                         result = WERR_NOMEM;
7776                         goto out;
7777                 }
7778
7779                 for (i=0; i<numlines; i++) {
7780                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7781                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7782                         if (!W_ERROR_IS_OK(result)) {
7783                                 goto out;
7784                         }
7785                 }
7786         }
7787         TALLOC_FREE(qlines);
7788
7789 out:
7790         if (!W_ERROR_IS_OK(result)) {
7791                 TALLOC_FREE(info);
7792                 TALLOC_FREE(qlines);
7793                 *count = 0;
7794                 *info_p = NULL;
7795                 return result;
7796         }
7797
7798         *info_p = info;
7799         *count = numlines;
7800
7801         return WERR_OK;
7802 }
7803
7804 /****************************************************************************
7805  enumports level 2.
7806 ****************************************************************************/
7807
7808 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7809                                 union spoolss_PortInfo **info_p,
7810                                 uint32_t *count)
7811 {
7812         union spoolss_PortInfo *info = NULL;
7813         int i=0;
7814         WERROR result = WERR_OK;
7815         char **qlines = NULL;
7816         int numlines = 0;
7817
7818         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7819         if (!W_ERROR_IS_OK(result)) {
7820                 goto out;
7821         }
7822
7823         if (numlines) {
7824                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7825                 if (!info) {
7826                         DEBUG(10,("Returning WERR_NOMEM\n"));
7827                         result = WERR_NOMEM;
7828                         goto out;
7829                 }
7830
7831                 for (i=0; i<numlines; i++) {
7832                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7833                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7834                         if (!W_ERROR_IS_OK(result)) {
7835                                 goto out;
7836                         }
7837                 }
7838         }
7839         TALLOC_FREE(qlines);
7840
7841 out:
7842         if (!W_ERROR_IS_OK(result)) {
7843                 TALLOC_FREE(info);
7844                 TALLOC_FREE(qlines);
7845                 *count = 0;
7846                 *info_p = NULL;
7847                 return result;
7848         }
7849
7850         *info_p = info;
7851         *count = numlines;
7852
7853         return WERR_OK;
7854 }
7855
7856 /****************************************************************
7857  _spoolss_EnumPorts
7858 ****************************************************************/
7859
7860 WERROR _spoolss_EnumPorts(pipes_struct *p,
7861                           struct spoolss_EnumPorts *r)
7862 {
7863         WERROR result;
7864
7865         /* that's an [in out] buffer */
7866
7867         if (!r->in.buffer && (r->in.offered != 0)) {
7868                 return WERR_INVALID_PARAM;
7869         }
7870
7871         DEBUG(4,("_spoolss_EnumPorts\n"));
7872
7873         *r->out.count = 0;
7874         *r->out.needed = 0;
7875         *r->out.info = NULL;
7876
7877         switch (r->in.level) {
7878         case 1:
7879                 result = enumports_level_1(p->mem_ctx, r->out.info,
7880                                            r->out.count);
7881                 break;
7882         case 2:
7883                 result = enumports_level_2(p->mem_ctx, r->out.info,
7884                                            r->out.count);
7885                 break;
7886         default:
7887                 return WERR_UNKNOWN_LEVEL;
7888         }
7889
7890         if (!W_ERROR_IS_OK(result)) {
7891                 return result;
7892         }
7893
7894         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7895                                                      spoolss_EnumPorts, NULL,
7896                                                      *r->out.info, r->in.level,
7897                                                      *r->out.count);
7898         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7899         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7900
7901         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7902 }
7903
7904 /****************************************************************************
7905 ****************************************************************************/
7906
7907 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7908                                            const char *server,
7909                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7910                                            struct spoolss_DeviceMode *devmode,
7911                                            struct security_descriptor *sec_desc,
7912                                            struct spoolss_UserLevelCtr *user_ctr,
7913                                            POLICY_HND *handle)
7914 {
7915         NT_PRINTER_INFO_LEVEL *printer = NULL;
7916         fstring name;
7917         int     snum;
7918         WERROR err = WERR_OK;
7919
7920         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7921                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7922                 return WERR_NOMEM;
7923         }
7924
7925         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7926         if (!convert_printer_info_new(info_ctr, printer)) {
7927                 free_a_printer(&printer, 2);
7928                 return WERR_NOMEM;
7929         }
7930
7931         /* check to see if the printer already exists */
7932
7933         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7934                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7935                         printer->info_2->sharename));
7936                 free_a_printer(&printer, 2);
7937                 return WERR_PRINTER_ALREADY_EXISTS;
7938         }
7939
7940         /* FIXME!!!  smbd should check to see if the driver is installed before
7941            trying to add a printer like this  --jerry */
7942
7943         if (*lp_addprinter_cmd() ) {
7944                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7945                                        printer) ) {
7946                         free_a_printer(&printer,2);
7947                         return WERR_ACCESS_DENIED;
7948                 }
7949         } else {
7950                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7951                         "smb.conf parameter \"addprinter command\" is defined. This"
7952                         "parameter must exist for this call to succeed\n",
7953                         printer->info_2->sharename ));
7954         }
7955
7956         /* use our primary netbios name since get_a_printer() will convert
7957            it to what the client expects on a case by case basis */
7958
7959         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7960              printer->info_2->sharename);
7961
7962
7963         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7964                 free_a_printer(&printer,2);
7965                 return WERR_ACCESS_DENIED;
7966         }
7967
7968         /* you must be a printer admin to add a new printer */
7969         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7970                 free_a_printer(&printer,2);
7971                 return WERR_ACCESS_DENIED;
7972         }
7973
7974         /*
7975          * Do sanity check on the requested changes for Samba.
7976          */
7977
7978         if (!check_printer_ok(printer->info_2, snum)) {
7979                 free_a_printer(&printer,2);
7980                 return WERR_INVALID_PARAM;
7981         }
7982
7983         /*
7984          * When a printer is created, the drivername bound to the printer is used
7985          * to lookup previously saved driver initialization info, which is then
7986          * bound to the new printer, simulating what happens in the Windows arch.
7987          */
7988
7989         if (!devmode)
7990         {
7991                 set_driver_init(printer, 2);
7992         }
7993         else
7994         {
7995                 /* A valid devmode was included, convert and link it
7996                 */
7997                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7998
7999                 if (!convert_devicemode_new(printer->info_2->printername,
8000                                             devmode,
8001                                             &printer->info_2->devmode))
8002                         return  WERR_NOMEM;
8003         }
8004
8005         /* write the ASCII on disk */
8006         err = mod_a_printer(printer, 2);
8007         if (!W_ERROR_IS_OK(err)) {
8008                 free_a_printer(&printer,2);
8009                 return err;
8010         }
8011
8012         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
8013                 /* Handle open failed - remove addition. */
8014                 del_a_printer(printer->info_2->sharename);
8015                 free_a_printer(&printer,2);
8016                 ZERO_STRUCTP(handle);
8017                 return WERR_ACCESS_DENIED;
8018         }
8019
8020         update_c_setprinter(False);
8021         free_a_printer(&printer,2);
8022
8023         return WERR_OK;
8024 }
8025
8026 /****************************************************************
8027  _spoolss_AddPrinterEx
8028 ****************************************************************/
8029
8030 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
8031                              struct spoolss_AddPrinterEx *r)
8032 {
8033         switch (r->in.info_ctr->level) {
8034         case 1:
8035                 /* we don't handle yet */
8036                 /* but I know what to do ... */
8037                 return WERR_UNKNOWN_LEVEL;
8038         case 2:
8039                 return spoolss_addprinterex_level_2(p, r->in.server,
8040                                                     r->in.info_ctr,
8041                                                     r->in.devmode_ctr->devmode,
8042                                                     r->in.secdesc_ctr->sd,
8043                                                     r->in.userlevel_ctr,
8044                                                     r->out.handle);
8045         default:
8046                 return WERR_UNKNOWN_LEVEL;
8047         }
8048 }
8049
8050 /****************************************************************
8051  _spoolss_AddPrinterDriver
8052 ****************************************************************/
8053
8054 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
8055                                  struct spoolss_AddPrinterDriver *r)
8056 {
8057         uint32_t level = r->in.info_ctr->level;
8058         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
8059         WERROR err = WERR_OK;
8060         NT_PRINTER_DRIVER_INFO_LEVEL driver;
8061         fstring driver_name;
8062         uint32 version;
8063         const char *fn;
8064
8065         switch (p->hdr_req.opnum) {
8066                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8067                         fn = "_spoolss_AddPrinterDriver";
8068                         break;
8069                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8070                         fn = "_spoolss_AddPrinterDriverEx";
8071                         break;
8072                 default:
8073                         return WERR_INVALID_PARAM;
8074         }
8075
8076
8077         /* FIXME */
8078         if (level != 3 && level != 6) {
8079                 /* Clever hack from Martin Zielinski <mz@seh.de>
8080                  * to allow downgrade from level 8 (Vista).
8081                  */
8082                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
8083                 return WERR_UNKNOWN_LEVEL;
8084         }
8085
8086         ZERO_STRUCT(driver);
8087
8088         if (!convert_printer_driver_info(info, &driver, level)) {
8089                 err = WERR_NOMEM;
8090                 goto done;
8091         }
8092
8093         DEBUG(5,("Cleaning driver's information\n"));
8094         err = clean_up_driver_struct(p, driver, level);
8095         if (!W_ERROR_IS_OK(err))
8096                 goto done;
8097
8098         DEBUG(5,("Moving driver to final destination\n"));
8099         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
8100                                                               &err)) ) {
8101                 goto done;
8102         }
8103
8104         if (add_a_printer_driver(driver, level)!=0) {
8105                 err = WERR_ACCESS_DENIED;
8106                 goto done;
8107         }
8108
8109         switch(level) {
8110         case 3:
8111                 fstrcpy(driver_name,
8112                         driver.info_3->name ? driver.info_3->name : "");
8113                 break;
8114         case 6:
8115                 fstrcpy(driver_name,
8116                         driver.info_6->name ?  driver.info_6->name : "");
8117                 break;
8118         }
8119
8120         /*
8121          * I think this is where he DrvUpgradePrinter() hook would be
8122          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8123          * server.  Right now, we just need to send ourselves a message
8124          * to update each printer bound to this driver.   --jerry
8125          */
8126
8127         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
8128                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8129                         fn, driver_name));
8130         }
8131
8132         /*
8133          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
8134          * decide if the driver init data should be deleted. The rules are:
8135          *  1) never delete init data if it is a 9x driver, they don't use it anyway
8136          *  2) delete init data only if there is no 2k/Xp driver
8137          *  3) always delete init data
8138          * The generalized rule is always use init data from the highest order driver.
8139          * It is necessary to follow the driver install by an initialization step to
8140          * finish off this process.
8141         */
8142         if (level == 3)
8143                 version = driver.info_3->cversion;
8144         else if (level == 6)
8145                 version = driver.info_6->version;
8146         else
8147                 version = -1;
8148         switch (version) {
8149                 /*
8150                  * 9x printer driver - never delete init data
8151                 */
8152                 case 0:
8153                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
8154                                 fn, driver_name));
8155                         break;
8156
8157                 /*
8158                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
8159                  * there is no 2k/Xp driver init data for this driver name.
8160                 */
8161                 case 2:
8162                 {
8163                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
8164
8165                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
8166                                 /*
8167                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8168                                 */
8169                                 if (!del_driver_init(driver_name))
8170                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
8171                                                 fn, driver_name));
8172                         } else {
8173                                 /*
8174                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8175                                 */
8176                                 free_a_printer_driver(driver1,3);
8177                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
8178                                         fn, driver_name));
8179                         }
8180                 }
8181                 break;
8182
8183                 /*
8184                  * 2k or Xp printer driver - always delete init data
8185                 */
8186                 case 3:
8187                         if (!del_driver_init(driver_name))
8188                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
8189                                         fn, driver_name));
8190                         break;
8191
8192                 default:
8193                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
8194                         break;
8195         }
8196
8197
8198 done:
8199         free_a_printer_driver(driver, level);
8200         return err;
8201 }
8202
8203 /****************************************************************
8204  _spoolss_AddPrinterDriverEx
8205 ****************************************************************/
8206
8207 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8208                                    struct spoolss_AddPrinterDriverEx *r)
8209 {
8210         struct spoolss_AddPrinterDriver a;
8211
8212         /*
8213          * we only support the semantics of AddPrinterDriver()
8214          * i.e. only copy files that are newer than existing ones
8215          */
8216
8217         if (r->in.flags != APD_COPY_NEW_FILES) {
8218                 return WERR_ACCESS_DENIED;
8219         }
8220
8221         a.in.servername         = r->in.servername;
8222         a.in.info_ctr           = r->in.info_ctr;
8223
8224         return _spoolss_AddPrinterDriver(p, &a);
8225 }
8226
8227 /****************************************************************************
8228 ****************************************************************************/
8229
8230 struct _spoolss_paths {
8231         int type;
8232         const char *share;
8233         const char *dir;
8234 };
8235
8236 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8237
8238 static const struct _spoolss_paths spoolss_paths[]= {
8239         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8240         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8241 };
8242
8243 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8244                                           const char *servername,
8245                                           const char *environment,
8246                                           int component,
8247                                           char **path)
8248 {
8249         const char *pservername = NULL;
8250         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8251         const char *short_archi;
8252
8253         *path = NULL;
8254
8255         /* environment may be empty */
8256         if (environment && strlen(environment)) {
8257                 long_archi = environment;
8258         }
8259
8260         /* servername may be empty */
8261         if (servername && strlen(servername)) {
8262                 pservername = canon_servername(servername);
8263
8264                 if (!is_myname_or_ipaddr(pservername)) {
8265                         return WERR_INVALID_PARAM;
8266                 }
8267         }
8268
8269         if (!(short_archi = get_short_archi(long_archi))) {
8270                 return WERR_INVALID_ENVIRONMENT;
8271         }
8272
8273         switch (component) {
8274         case SPOOLSS_PRTPROCS_PATH:
8275         case SPOOLSS_DRIVER_PATH:
8276                 if (pservername) {
8277                         *path = talloc_asprintf(mem_ctx,
8278                                         "\\\\%s\\%s\\%s",
8279                                         pservername,
8280                                         spoolss_paths[component].share,
8281                                         short_archi);
8282                 } else {
8283                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8284                                         SPOOLSS_DEFAULT_SERVER_PATH,
8285                                         spoolss_paths[component].dir,
8286                                         short_archi);
8287                 }
8288                 break;
8289         default:
8290                 return WERR_INVALID_PARAM;
8291         }
8292
8293         if (!*path) {
8294                 return WERR_NOMEM;
8295         }
8296
8297         return WERR_OK;
8298 }
8299
8300 /****************************************************************************
8301 ****************************************************************************/
8302
8303 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8304                                           const char *servername,
8305                                           const char *environment,
8306                                           struct spoolss_DriverDirectoryInfo1 *r)
8307 {
8308         WERROR werr;
8309         char *path = NULL;
8310
8311         werr = compose_spoolss_server_path(mem_ctx,
8312                                            servername,
8313                                            environment,
8314                                            SPOOLSS_DRIVER_PATH,
8315                                            &path);
8316         if (!W_ERROR_IS_OK(werr)) {
8317                 return werr;
8318         }
8319
8320         DEBUG(4,("printer driver directory: [%s]\n", path));
8321
8322         r->directory_name = path;
8323
8324         return WERR_OK;
8325 }
8326
8327 /****************************************************************
8328  _spoolss_GetPrinterDriverDirectory
8329 ****************************************************************/
8330
8331 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8332                                           struct spoolss_GetPrinterDriverDirectory *r)
8333 {
8334         WERROR werror;
8335
8336         /* that's an [in out] buffer */
8337
8338         if (!r->in.buffer && (r->in.offered != 0)) {
8339                 return WERR_INVALID_PARAM;
8340         }
8341
8342         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8343                 r->in.level));
8344
8345         *r->out.needed = 0;
8346
8347         /* r->in.level is ignored */
8348
8349         werror = getprinterdriverdir_level_1(p->mem_ctx,
8350                                              r->in.server,
8351                                              r->in.environment,
8352                                              &r->out.info->info1);
8353         if (!W_ERROR_IS_OK(werror)) {
8354                 TALLOC_FREE(r->out.info);
8355                 return werror;
8356         }
8357
8358         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
8359                                                r->out.info, r->in.level);
8360         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8361
8362         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8363 }
8364
8365 /****************************************************************************
8366 ****************************************************************************/
8367
8368 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8369 {
8370         POLICY_HND *handle = &q_u->handle;
8371         uint32 idx               = q_u->index;
8372         uint32 in_value_len      = q_u->valuesize;
8373         uint32 in_data_len       = q_u->datasize;
8374         uint32 *out_max_value_len = &r_u->valuesize;
8375         uint16 **out_value       = &r_u->value;
8376         uint32 *out_value_len    = &r_u->realvaluesize;
8377         uint32 *out_type         = &r_u->type;
8378         uint32 *out_max_data_len = &r_u->datasize;
8379         uint8  **data_out        = &r_u->data;
8380         uint32 *out_data_len     = &r_u->realdatasize;
8381
8382         NT_PRINTER_INFO_LEVEL *printer = NULL;
8383
8384         uint32          biggest_valuesize;
8385         uint32          biggest_datasize;
8386         uint32          data_len;
8387         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8388         int             snum;
8389         WERROR          result;
8390         REGISTRY_VALUE  *val = NULL;
8391         NT_PRINTER_DATA *p_data;
8392         int             i, key_index, num_values;
8393         int             name_length;
8394
8395         *out_type = 0;
8396
8397         *out_max_data_len = 0;
8398         *data_out         = NULL;
8399         *out_data_len     = 0;
8400
8401         DEBUG(5,("spoolss_enumprinterdata\n"));
8402
8403         if (!Printer) {
8404                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8405                 return WERR_BADFID;
8406         }
8407
8408         if (!get_printer_snum(p,handle, &snum, NULL))
8409                 return WERR_BADFID;
8410
8411         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8412         if (!W_ERROR_IS_OK(result))
8413                 return result;
8414
8415         p_data = printer->info_2->data;
8416         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8417
8418         result = WERR_OK;
8419
8420         /*
8421          * The NT machine wants to know the biggest size of value and data
8422          *
8423          * cf: MSDN EnumPrinterData remark section
8424          */
8425
8426         if ( !in_value_len && !in_data_len && (key_index != -1) )
8427         {
8428                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8429
8430                 biggest_valuesize = 0;
8431                 biggest_datasize  = 0;
8432
8433                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8434
8435                 for ( i=0; i<num_values; i++ )
8436                 {
8437                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8438
8439                         name_length = strlen(val->valuename);
8440                         if ( strlen(val->valuename) > biggest_valuesize )
8441                                 biggest_valuesize = name_length;
8442
8443                         if ( val->size > biggest_datasize )
8444                                 biggest_datasize = val->size;
8445
8446                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8447                                 biggest_datasize));
8448                 }
8449
8450                 /* the value is an UNICODE string but real_value_size is the length
8451                    in bytes including the trailing 0 */
8452
8453                 *out_value_len = 2 * (1+biggest_valuesize);
8454                 *out_data_len  = biggest_datasize;
8455
8456                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8457
8458                 goto done;
8459         }
8460
8461         /*
8462          * the value len is wrong in NT sp3
8463          * that's the number of bytes not the number of unicode chars
8464          */
8465
8466         if ( key_index != -1 )
8467                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8468
8469         if ( !val )
8470         {
8471
8472                 /* out_value should default to "" or else NT4 has
8473                    problems unmarshalling the response */
8474
8475                 *out_max_value_len=(in_value_len/sizeof(uint16));
8476
8477                 if (in_value_len) {
8478                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8479                         {
8480                                 result = WERR_NOMEM;
8481                                 goto done;
8482                         }
8483                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8484                 } else {
8485                         *out_value=NULL;
8486                         *out_value_len = 0;
8487                 }
8488
8489                 /* the data is counted in bytes */
8490
8491                 *out_max_data_len = in_data_len;
8492                 *out_data_len     = in_data_len;
8493
8494                 /* only allocate when given a non-zero data_len */
8495
8496                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8497                 {
8498                         result = WERR_NOMEM;
8499                         goto done;
8500                 }
8501
8502                 result = WERR_NO_MORE_ITEMS;
8503         }
8504         else
8505         {
8506                 /*
8507                  * the value is:
8508                  * - counted in bytes in the request
8509                  * - counted in UNICODE chars in the max reply
8510                  * - counted in bytes in the real size
8511                  *
8512                  * take a pause *before* coding not *during* coding
8513                  */
8514
8515                 /* name */
8516                 *out_max_value_len=(in_value_len/sizeof(uint16));
8517                 if (in_value_len) {
8518                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8519                         {
8520                                 result = WERR_NOMEM;
8521                                 goto done;
8522                         }
8523
8524                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8525                 } else {
8526                         *out_value = NULL;
8527                         *out_value_len = 0;
8528                 }
8529
8530                 /* type */
8531
8532                 *out_type = regval_type( val );
8533
8534                 /* data - counted in bytes */
8535
8536                 *out_max_data_len = in_data_len;
8537                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8538                 {
8539                         result = WERR_NOMEM;
8540                         goto done;
8541                 }
8542                 data_len = regval_size(val);
8543                 if ( *data_out && data_len )
8544                         memcpy( *data_out, regval_data_p(val), data_len );
8545                 *out_data_len = data_len;
8546         }
8547
8548 done:
8549         free_a_printer(&printer, 2);
8550         return result;
8551 }
8552
8553 /****************************************************************************
8554 ****************************************************************************/
8555
8556 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8557 {
8558         POLICY_HND              *handle = &q_u->handle;
8559         UNISTR2                 *value = &q_u->value;
8560         uint32                  type = q_u->type;
8561         uint8                   *data = q_u->data;
8562         uint32                  real_len = q_u->real_len;
8563
8564         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8565         int                     snum=0;
8566         WERROR                  status = WERR_OK;
8567         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8568         fstring                 valuename;
8569
8570         DEBUG(5,("spoolss_setprinterdata\n"));
8571
8572         if (!Printer) {
8573                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8574                 return WERR_BADFID;
8575         }
8576
8577         if ( Printer->printer_type == SPLHND_SERVER ) {
8578                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8579                 return WERR_INVALID_PARAM;
8580         }
8581
8582         if (!get_printer_snum(p,handle, &snum, NULL))
8583                 return WERR_BADFID;
8584
8585         /*
8586          * Access check : NT returns "access denied" if you make a
8587          * SetPrinterData call without the necessary privildge.
8588          * we were originally returning OK if nothing changed
8589          * which made Win2k issue **a lot** of SetPrinterData
8590          * when connecting to a printer  --jerry
8591          */
8592
8593         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8594         {
8595                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8596                 status = WERR_ACCESS_DENIED;
8597                 goto done;
8598         }
8599
8600         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8601         if (!W_ERROR_IS_OK(status))
8602                 return status;
8603
8604         unistr2_to_ascii(valuename, value, sizeof(valuename));
8605
8606         /*
8607          * When client side code sets a magic printer data key, detect it and save
8608          * the current printer data and the magic key's data (its the DEVMODE) for
8609          * future printer/driver initializations.
8610          */
8611         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8612         {
8613                 /* Set devmode and printer initialization info */
8614                 status = save_driver_init( printer, 2, data, real_len );
8615
8616                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8617         }
8618         else
8619         {
8620         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8621                                         type, data, real_len );
8622                 if ( W_ERROR_IS_OK(status) )
8623                         status = mod_a_printer(printer, 2);
8624         }
8625
8626 done:
8627         free_a_printer(&printer, 2);
8628
8629         return status;
8630 }
8631
8632 /****************************************************************
8633  _spoolss_ResetPrinter
8634 ****************************************************************/
8635
8636 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8637                              struct spoolss_ResetPrinter *r)
8638 {
8639         POLICY_HND      *handle = r->in.handle;
8640         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8641         int             snum;
8642
8643         DEBUG(5,("_spoolss_ResetPrinter\n"));
8644
8645         /*
8646          * All we do is to check to see if the handle and queue is valid.
8647          * This call really doesn't mean anything to us because we only
8648          * support RAW printing.   --jerry
8649          */
8650
8651         if (!Printer) {
8652                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8653                         OUR_HANDLE(handle)));
8654                 return WERR_BADFID;
8655         }
8656
8657         if (!get_printer_snum(p,handle, &snum, NULL))
8658                 return WERR_BADFID;
8659
8660
8661         /* blindly return success */
8662         return WERR_OK;
8663 }
8664
8665 /****************************************************************
8666  _spoolss_DeletePrinterData
8667 ****************************************************************/
8668
8669 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8670                                   struct spoolss_DeletePrinterData *r)
8671 {
8672         POLICY_HND      *handle = r->in.handle;
8673         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8674         int             snum=0;
8675         WERROR          status = WERR_OK;
8676         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8677
8678         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8679
8680         if (!Printer) {
8681                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8682                         OUR_HANDLE(handle)));
8683                 return WERR_BADFID;
8684         }
8685
8686         if (!get_printer_snum(p, handle, &snum, NULL))
8687                 return WERR_BADFID;
8688
8689         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8690                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8691                         "printer properties change denied by handle\n"));
8692                 return WERR_ACCESS_DENIED;
8693         }
8694
8695         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8696         if (!W_ERROR_IS_OK(status))
8697                 return status;
8698
8699         if (!r->in.value_name) {
8700                 free_a_printer(&printer, 2);
8701                 return WERR_NOMEM;
8702         }
8703
8704         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8705                                         r->in.value_name );
8706
8707         if ( W_ERROR_IS_OK(status) )
8708                 mod_a_printer( printer, 2 );
8709
8710         free_a_printer(&printer, 2);
8711
8712         return status;
8713 }
8714
8715 /****************************************************************
8716  _spoolss_AddForm
8717 ****************************************************************/
8718
8719 WERROR _spoolss_AddForm(pipes_struct *p,
8720                         struct spoolss_AddForm *r)
8721 {
8722         POLICY_HND *handle = r->in.handle;
8723         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8724         nt_forms_struct tmpForm;
8725         int snum;
8726         WERROR status = WERR_OK;
8727         NT_PRINTER_INFO_LEVEL *printer = NULL;
8728
8729         int count=0;
8730         nt_forms_struct *list=NULL;
8731         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8732
8733         DEBUG(5,("_spoolss_AddForm\n"));
8734
8735         if (!Printer) {
8736                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8737                         OUR_HANDLE(handle)));
8738                 return WERR_BADFID;
8739         }
8740
8741
8742         /* forms can be added on printer of on the print server handle */
8743
8744         if ( Printer->printer_type == SPLHND_PRINTER )
8745         {
8746                 if (!get_printer_snum(p,handle, &snum, NULL))
8747                         return WERR_BADFID;
8748
8749                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8750                 if (!W_ERROR_IS_OK(status))
8751                         goto done;
8752         }
8753
8754         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8755                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8756                 status = WERR_ACCESS_DENIED;
8757                 goto done;
8758         }
8759
8760         /* can't add if builtin */
8761
8762         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8763                 status = WERR_FILE_EXISTS;
8764                 goto done;
8765         }
8766
8767         count = get_ntforms(&list);
8768
8769         if(!add_a_form(&list, form, &count)) {
8770                 status =  WERR_NOMEM;
8771                 goto done;
8772         }
8773
8774         write_ntforms(&list, count);
8775
8776         /*
8777          * ChangeID must always be set if this is a printer
8778          */
8779
8780         if ( Printer->printer_type == SPLHND_PRINTER )
8781                 status = mod_a_printer(printer, 2);
8782
8783 done:
8784         if ( printer )
8785                 free_a_printer(&printer, 2);
8786         SAFE_FREE(list);
8787
8788         return status;
8789 }
8790
8791 /****************************************************************
8792  _spoolss_DeleteForm
8793 ****************************************************************/
8794
8795 WERROR _spoolss_DeleteForm(pipes_struct *p,
8796                            struct spoolss_DeleteForm *r)
8797 {
8798         POLICY_HND *handle = r->in.handle;
8799         const char *form_name = r->in.form_name;
8800         nt_forms_struct tmpForm;
8801         int count=0;
8802         nt_forms_struct *list=NULL;
8803         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8804         int snum;
8805         WERROR status = WERR_OK;
8806         NT_PRINTER_INFO_LEVEL *printer = NULL;
8807
8808         DEBUG(5,("_spoolss_DeleteForm\n"));
8809
8810         if (!Printer) {
8811                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8812                         OUR_HANDLE(handle)));
8813                 return WERR_BADFID;
8814         }
8815
8816         /* forms can be deleted on printer of on the print server handle */
8817
8818         if ( Printer->printer_type == SPLHND_PRINTER )
8819         {
8820                 if (!get_printer_snum(p,handle, &snum, NULL))
8821                         return WERR_BADFID;
8822
8823                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8824                 if (!W_ERROR_IS_OK(status))
8825                         goto done;
8826         }
8827
8828         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8829                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8830                 status = WERR_ACCESS_DENIED;
8831                 goto done;
8832         }
8833
8834         /* can't delete if builtin */
8835
8836         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8837                 status = WERR_INVALID_PARAM;
8838                 goto done;
8839         }
8840
8841         count = get_ntforms(&list);
8842
8843         if ( !delete_a_form(&list, form_name, &count, &status ))
8844                 goto done;
8845
8846         /*
8847          * ChangeID must always be set if this is a printer
8848          */
8849
8850         if ( Printer->printer_type == SPLHND_PRINTER )
8851                 status = mod_a_printer(printer, 2);
8852
8853 done:
8854         if ( printer )
8855                 free_a_printer(&printer, 2);
8856         SAFE_FREE(list);
8857
8858         return status;
8859 }
8860
8861 /****************************************************************
8862  _spoolss_SetForm
8863 ****************************************************************/
8864
8865 WERROR _spoolss_SetForm(pipes_struct *p,
8866                         struct spoolss_SetForm *r)
8867 {
8868         POLICY_HND *handle = r->in.handle;
8869         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8870         nt_forms_struct tmpForm;
8871         int snum;
8872         WERROR status = WERR_OK;
8873         NT_PRINTER_INFO_LEVEL *printer = NULL;
8874
8875         int count=0;
8876         nt_forms_struct *list=NULL;
8877         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8878
8879         DEBUG(5,("_spoolss_SetForm\n"));
8880
8881         if (!Printer) {
8882                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8883                         OUR_HANDLE(handle)));
8884                 return WERR_BADFID;
8885         }
8886
8887         /* forms can be modified on printer of on the print server handle */
8888
8889         if ( Printer->printer_type == SPLHND_PRINTER )
8890         {
8891                 if (!get_printer_snum(p,handle, &snum, NULL))
8892                         return WERR_BADFID;
8893
8894                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8895                 if (!W_ERROR_IS_OK(status))
8896                         goto done;
8897         }
8898
8899         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8900                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8901                 status = WERR_ACCESS_DENIED;
8902                 goto done;
8903         }
8904
8905         /* can't set if builtin */
8906         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8907                 status = WERR_INVALID_PARAM;
8908                 goto done;
8909         }
8910
8911         count = get_ntforms(&list);
8912         update_a_form(&list, form, count);
8913         write_ntforms(&list, count);
8914
8915         /*
8916          * ChangeID must always be set if this is a printer
8917          */
8918
8919         if ( Printer->printer_type == SPLHND_PRINTER )
8920                 status = mod_a_printer(printer, 2);
8921
8922
8923 done:
8924         if ( printer )
8925                 free_a_printer(&printer, 2);
8926         SAFE_FREE(list);
8927
8928         return status;
8929 }
8930
8931 /****************************************************************************
8932  fill_print_processor1
8933 ****************************************************************************/
8934
8935 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8936                                     struct spoolss_PrintProcessorInfo1 *r,
8937                                     const char *print_processor_name)
8938 {
8939         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8940         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8941
8942         return WERR_OK;
8943 }
8944
8945 /****************************************************************************
8946  enumprintprocessors level 1.
8947 ****************************************************************************/
8948
8949 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8950                                           union spoolss_PrintProcessorInfo **info_p,
8951                                           uint32_t *count)
8952 {
8953         union spoolss_PrintProcessorInfo *info;
8954         WERROR result;
8955
8956         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8957         W_ERROR_HAVE_NO_MEMORY(info);
8958
8959         *count = 1;
8960
8961         result = fill_print_processor1(info, &info[0].info1, "winprint");
8962         if (!W_ERROR_IS_OK(result)) {
8963                 goto out;
8964         }
8965
8966  out:
8967         if (!W_ERROR_IS_OK(result)) {
8968                 TALLOC_FREE(info);
8969                 *count = 0;
8970                 return result;
8971         }
8972
8973         *info_p = info;
8974
8975         return WERR_OK;
8976 }
8977
8978 /****************************************************************
8979  _spoolss_EnumPrintProcessors
8980 ****************************************************************/
8981
8982 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8983                                     struct spoolss_EnumPrintProcessors *r)
8984 {
8985         WERROR result;
8986
8987         /* that's an [in out] buffer */
8988
8989         if (!r->in.buffer && (r->in.offered != 0)) {
8990                 return WERR_INVALID_PARAM;
8991         }
8992
8993         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8994
8995         /*
8996          * Enumerate the print processors ...
8997          *
8998          * Just reply with "winprint", to keep NT happy
8999          * and I can use my nice printer checker.
9000          */
9001
9002         *r->out.count = 0;
9003         *r->out.needed = 0;
9004         *r->out.info = NULL;
9005
9006         switch (r->in.level) {
9007         case 1:
9008                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9009                                                      r->out.count);
9010                 break;
9011         default:
9012                 return WERR_UNKNOWN_LEVEL;
9013         }
9014
9015         if (!W_ERROR_IS_OK(result)) {
9016                 return result;
9017         }
9018
9019         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9020                                                      spoolss_EnumPrintProcessors, NULL,
9021                                                      *r->out.info, r->in.level,
9022                                                      *r->out.count);
9023         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9024         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9025
9026         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9027 }
9028
9029 /****************************************************************************
9030  fill_printprocdatatype1
9031 ****************************************************************************/
9032
9033 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9034                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9035                                       const char *name_array)
9036 {
9037         r->name_array = talloc_strdup(mem_ctx, name_array);
9038         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9039
9040         return WERR_OK;
9041 }
9042
9043 /****************************************************************************
9044  enumprintprocdatatypes level 1.
9045 ****************************************************************************/
9046
9047 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9048                                              union spoolss_PrintProcDataTypesInfo **info_p,
9049                                              uint32_t *count)
9050 {
9051         WERROR result;
9052         union spoolss_PrintProcDataTypesInfo *info;
9053
9054         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9055         W_ERROR_HAVE_NO_MEMORY(info);
9056
9057         *count = 1;
9058
9059         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9060         if (!W_ERROR_IS_OK(result)) {
9061                 goto out;
9062         }
9063
9064  out:
9065         if (!W_ERROR_IS_OK(result)) {
9066                 TALLOC_FREE(info);
9067                 *count = 0;
9068                 return result;
9069         }
9070
9071         *info_p = info;
9072
9073         return WERR_OK;
9074 }
9075
9076 /****************************************************************
9077  _spoolss_EnumPrintProcDataTypes
9078 ****************************************************************/
9079
9080 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
9081                                        struct spoolss_EnumPrintProcDataTypes *r)
9082 {
9083         WERROR result;
9084
9085         /* that's an [in out] buffer */
9086
9087         if (!r->in.buffer && (r->in.offered != 0)) {
9088                 return WERR_INVALID_PARAM;
9089         }
9090
9091         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9092
9093         *r->out.count = 0;
9094         *r->out.needed = 0;
9095         *r->out.info = NULL;
9096
9097         switch (r->in.level) {
9098         case 1:
9099                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9100                                                         r->out.count);
9101                 break;
9102         default:
9103                 return WERR_UNKNOWN_LEVEL;
9104         }
9105
9106         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9107                                                      spoolss_EnumPrintProcDataTypes, NULL,
9108                                                      *r->out.info, r->in.level,
9109                                                      *r->out.count);
9110         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9111         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9112
9113         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9114 }
9115
9116 /****************************************************************************
9117  fill_monitor_1
9118 ****************************************************************************/
9119
9120 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9121                              struct spoolss_MonitorInfo1 *r,
9122                              const char *monitor_name)
9123 {
9124         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9125         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9126
9127         return WERR_OK;
9128 }
9129
9130 /****************************************************************************
9131  fill_monitor_2
9132 ****************************************************************************/
9133
9134 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9135                              struct spoolss_MonitorInfo2 *r,
9136                              const char *monitor_name,
9137                              const char *environment,
9138                              const char *dll_name)
9139 {
9140         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9141         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9142         r->environment                  = talloc_strdup(mem_ctx, environment);
9143         W_ERROR_HAVE_NO_MEMORY(r->environment);
9144         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9145         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9146
9147         return WERR_OK;
9148 }
9149
9150 /****************************************************************************
9151  enumprintmonitors level 1.
9152 ****************************************************************************/
9153
9154 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9155                                         union spoolss_MonitorInfo **info_p,
9156                                         uint32_t *count)
9157 {
9158         union spoolss_MonitorInfo *info;
9159         WERROR result = WERR_OK;
9160
9161         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9162         W_ERROR_HAVE_NO_MEMORY(info);
9163
9164         *count = 2;
9165
9166         result = fill_monitor_1(info, &info[0].info1,
9167                                 SPL_LOCAL_PORT /* FIXME */);
9168         if (!W_ERROR_IS_OK(result)) {
9169                 goto out;
9170         }
9171
9172         result = fill_monitor_1(info, &info[1].info1,
9173                                 SPL_TCPIP_PORT /* FIXME */);
9174         if (!W_ERROR_IS_OK(result)) {
9175                 goto out;
9176         }
9177
9178 out:
9179         if (!W_ERROR_IS_OK(result)) {
9180                 TALLOC_FREE(info);
9181                 *count = 0;
9182                 return result;
9183         }
9184
9185         *info_p = info;
9186
9187         return WERR_OK;
9188 }
9189
9190 /****************************************************************************
9191  enumprintmonitors level 2.
9192 ****************************************************************************/
9193
9194 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9195                                         union spoolss_MonitorInfo **info_p,
9196                                         uint32_t *count)
9197 {
9198         union spoolss_MonitorInfo *info;
9199         WERROR result = WERR_OK;
9200
9201         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9202         W_ERROR_HAVE_NO_MEMORY(info);
9203
9204         *count = 2;
9205
9206         result = fill_monitor_2(info, &info[0].info2,
9207                                 SPL_LOCAL_PORT, /* FIXME */
9208                                 "Windows NT X86", /* FIXME */
9209                                 "localmon.dll");
9210         if (!W_ERROR_IS_OK(result)) {
9211                 goto out;
9212         }
9213
9214         result = fill_monitor_2(info, &info[1].info2,
9215                                 SPL_TCPIP_PORT, /* FIXME */
9216                                 "Windows NT X86", /* FIXME */
9217                                 "tcpmon.dll");
9218         if (!W_ERROR_IS_OK(result)) {
9219                 goto out;
9220         }
9221
9222 out:
9223         if (!W_ERROR_IS_OK(result)) {
9224                 TALLOC_FREE(info);
9225                 *count = 0;
9226                 return result;
9227         }
9228
9229         *info_p = info;
9230
9231         return WERR_OK;
9232 }
9233
9234 /****************************************************************
9235  _spoolss_EnumMonitors
9236 ****************************************************************/
9237
9238 WERROR _spoolss_EnumMonitors(pipes_struct *p,
9239                              struct spoolss_EnumMonitors *r)
9240 {
9241         WERROR result;
9242
9243         /* that's an [in out] buffer */
9244
9245         if (!r->in.buffer && (r->in.offered != 0)) {
9246                 return WERR_INVALID_PARAM;
9247         }
9248
9249         DEBUG(5,("_spoolss_EnumMonitors\n"));
9250
9251         /*
9252          * Enumerate the print monitors ...
9253          *
9254          * Just reply with "Local Port", to keep NT happy
9255          * and I can use my nice printer checker.
9256          */
9257
9258         *r->out.count = 0;
9259         *r->out.needed = 0;
9260         *r->out.info = NULL;
9261
9262         switch (r->in.level) {
9263         case 1:
9264                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9265                                                    r->out.count);
9266                 break;
9267         case 2:
9268                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9269                                                    r->out.count);
9270                 break;
9271         default:
9272                 return WERR_UNKNOWN_LEVEL;
9273         }
9274
9275         if (!W_ERROR_IS_OK(result)) {
9276                 return result;
9277         }
9278
9279         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9280                                                      spoolss_EnumMonitors, NULL,
9281                                                      *r->out.info, r->in.level,
9282                                                      *r->out.count);
9283         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9284         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9285
9286         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9287 }
9288
9289 /****************************************************************************
9290 ****************************************************************************/
9291
9292 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9293                              const print_queue_struct *queue,
9294                              int count, int snum,
9295                              const NT_PRINTER_INFO_LEVEL *ntprinter,
9296                              uint32_t jobid,
9297                              struct spoolss_JobInfo1 *r)
9298 {
9299         int i = 0;
9300         bool found = false;
9301
9302         for (i=0; i<count && found == false; i++) {
9303                 if (queue[i].job == (int)jobid) {
9304                         found = true;
9305                 }
9306         }
9307
9308         if (found == false) {
9309                 /* NT treats not found as bad param... yet another bad choice */
9310                 return WERR_INVALID_PARAM;
9311         }
9312
9313         return fill_job_info1(mem_ctx,
9314                               r,
9315                               &queue[i-1],
9316                               i,
9317                               snum,
9318                               ntprinter);
9319 }
9320
9321 /****************************************************************************
9322 ****************************************************************************/
9323
9324 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9325                              const print_queue_struct *queue,
9326                              int count, int snum,
9327                              const NT_PRINTER_INFO_LEVEL *ntprinter,
9328                              uint32_t jobid,
9329                              struct spoolss_JobInfo2 *r)
9330 {
9331         int i = 0;
9332         bool found = false;
9333         struct spoolss_DeviceMode *devmode;
9334         NT_DEVICEMODE *nt_devmode;
9335         WERROR result;
9336
9337         for (i=0; i<count && found == false; i++) {
9338                 if (queue[i].job == (int)jobid) {
9339                         found = true;
9340                 }
9341         }
9342
9343         if (found == false) {
9344                 /* NT treats not found as bad param... yet another bad
9345                    choice */
9346                 return WERR_INVALID_PARAM;
9347         }
9348
9349         /*
9350          * if the print job does not have a DEVMODE associated with it,
9351          * just use the one for the printer. A NULL devicemode is not
9352          *  a failure condition
9353          */
9354
9355         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9356         if (nt_devmode) {
9357                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
9358                 W_ERROR_HAVE_NO_MEMORY(devmode);
9359                 result = convert_nt_devicemode_new(devmode, devmode, nt_devmode);
9360                 if (!W_ERROR_IS_OK(result)) {
9361                         return result;
9362                 }
9363         } else {
9364                 devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
9365                 W_ERROR_HAVE_NO_MEMORY(devmode);
9366         }
9367
9368         return fill_job_info2(mem_ctx,
9369                               r,
9370                               &queue[i-1],
9371                               i,
9372                               snum,
9373                               ntprinter,
9374                               devmode);
9375 }
9376
9377 /****************************************************************
9378  _spoolss_GetJob
9379 ****************************************************************/
9380
9381 WERROR _spoolss_GetJob(pipes_struct *p,
9382                        struct spoolss_GetJob *r)
9383 {
9384         WERROR result = WERR_OK;
9385         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9386         int snum;
9387         int count;
9388         print_queue_struct      *queue = NULL;
9389         print_status_struct prt_status;
9390
9391         /* that's an [in out] buffer */
9392
9393         if (!r->in.buffer && (r->in.offered != 0)) {
9394                 return WERR_INVALID_PARAM;
9395         }
9396
9397         DEBUG(5,("_spoolss_GetJob\n"));
9398
9399         *r->out.needed = 0;
9400
9401         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9402                 return WERR_BADFID;
9403         }
9404
9405         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9406         if (!W_ERROR_IS_OK(result)) {
9407                 return result;
9408         }
9409
9410         count = print_queue_status(snum, &queue, &prt_status);
9411
9412         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9413                      count, prt_status.status, prt_status.message));
9414
9415         switch (r->in.level) {
9416         case 1:
9417                 result = getjob_level_1(p->mem_ctx,
9418                                         queue, count, snum, ntprinter,
9419                                         r->in.job_id, &r->out.info->info1);
9420                 break;
9421         case 2:
9422                 result = getjob_level_2(p->mem_ctx,
9423                                         queue, count, snum, ntprinter,
9424                                         r->in.job_id, &r->out.info->info2);
9425                 break;
9426         default:
9427                 result = WERR_UNKNOWN_LEVEL;
9428                 break;
9429         }
9430
9431         SAFE_FREE(queue);
9432         free_a_printer(&ntprinter, 2);
9433
9434         if (!W_ERROR_IS_OK(result)) {
9435                 TALLOC_FREE(r->out.info);
9436                 return result;
9437         }
9438
9439         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9440                                                r->out.info, r->in.level);
9441         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9442
9443         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9444 }
9445
9446 /****************************************************************
9447  _spoolss_GetPrinterDataEx
9448
9449  From MSDN documentation of GetPrinterDataEx: pass request
9450  to GetPrinterData if key is "PrinterDriverData".
9451 ****************************************************************/
9452
9453 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9454                                  struct spoolss_GetPrinterDataEx *r)
9455 {
9456         POLICY_HND      *handle = r->in.handle;
9457         uint8           *data = NULL;
9458         const char      *keyname = r->in.key_name;
9459         const char      *valuename = r->in.value_name;
9460
9461         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9462
9463         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9464         int                     snum = 0;
9465         WERROR                  status = WERR_OK;
9466
9467         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9468
9469         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9470                 keyname, valuename));
9471
9472         /* in case of problem, return some default values */
9473
9474         *r->out.needed  = 0;
9475         *r->out.type    = 0;
9476
9477         if (!Printer) {
9478                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9479                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9480                 status = WERR_BADFID;
9481                 goto done;
9482         }
9483
9484         /* Is the handle to a printer or to the server? */
9485
9486         if (Printer->printer_type == SPLHND_SERVER) {
9487                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9488                         "Not implemented for server handles yet\n"));
9489                 status = WERR_INVALID_PARAM;
9490                 goto done;
9491         }
9492
9493         if ( !get_printer_snum(p,handle, &snum, NULL) )
9494                 return WERR_BADFID;
9495
9496         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9497         if ( !W_ERROR_IS_OK(status) )
9498                 goto done;
9499
9500         /* check to see if the keyname is valid */
9501         if ( !strlen(keyname) ) {
9502                 status = WERR_INVALID_PARAM;
9503                 goto done;
9504         }
9505
9506         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9507                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9508                         "Invalid keyname [%s]\n", keyname ));
9509                 free_a_printer( &printer, 2 );
9510                 status = WERR_BADFILE;
9511                 goto done;
9512         }
9513
9514         /* When given a new keyname, we should just create it */
9515
9516         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9517                                      r->out.type, &data, r->out.needed,
9518                                      r->in.offered );
9519
9520         if (*r->out.needed > r->in.offered) {
9521                 status = WERR_MORE_DATA;
9522         }
9523
9524         if (W_ERROR_IS_OK(status)) {
9525                 memcpy(r->out.buffer, data, r->in.offered);
9526         }
9527
9528 done:
9529         if ( printer )
9530         free_a_printer( &printer, 2 );
9531
9532         return status;
9533 }
9534
9535 /****************************************************************
9536  _spoolss_SetPrinterDataEx
9537 ****************************************************************/
9538
9539 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9540                                  struct spoolss_SetPrinterDataEx *r)
9541 {
9542         POLICY_HND              *handle = r->in.handle;
9543         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9544         int                     snum = 0;
9545         WERROR                  status = WERR_OK;
9546         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9547         char                    *oid_string;
9548
9549         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9550
9551         /* From MSDN documentation of SetPrinterDataEx: pass request to
9552            SetPrinterData if key is "PrinterDriverData" */
9553
9554         if (!Printer) {
9555                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9556                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9557                 return WERR_BADFID;
9558         }
9559
9560         if ( Printer->printer_type == SPLHND_SERVER ) {
9561                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9562                         "Not implemented for server handles yet\n"));
9563                 return WERR_INVALID_PARAM;
9564         }
9565
9566         if ( !get_printer_snum(p,handle, &snum, NULL) )
9567                 return WERR_BADFID;
9568
9569         /*
9570          * Access check : NT returns "access denied" if you make a
9571          * SetPrinterData call without the necessary privildge.
9572          * we were originally returning OK if nothing changed
9573          * which made Win2k issue **a lot** of SetPrinterData
9574          * when connecting to a printer  --jerry
9575          */
9576
9577         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9578         {
9579                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9580                         "change denied by handle access permissions\n"));
9581                 return WERR_ACCESS_DENIED;
9582         }
9583
9584         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9585         if (!W_ERROR_IS_OK(status))
9586                 return status;
9587
9588         /* check for OID in valuename */
9589
9590         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9591         {
9592                 *oid_string = '\0';
9593                 oid_string++;
9594         }
9595
9596         /* save the registry data */
9597
9598         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9599                                      r->in.type, r->in.buffer, r->in.offered );
9600
9601         if ( W_ERROR_IS_OK(status) )
9602         {
9603                 /* save the OID if one was specified */
9604                 if ( oid_string ) {
9605                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9606                                 r->in.key_name, SPOOL_OID_KEY);
9607                         if (!str) {
9608                                 return WERR_NOMEM;
9609                         }
9610
9611                         /*
9612                          * I'm not checking the status here on purpose.  Don't know
9613                          * if this is right, but I'm returning the status from the
9614                          * previous set_printer_dataex() call.  I have no idea if
9615                          * this is right.    --jerry
9616                          */
9617
9618                         set_printer_dataex( printer, str, r->in.value_name,
9619                                             REG_SZ, (uint8 *)oid_string,
9620                                             strlen(oid_string)+1 );
9621                 }
9622
9623                 status = mod_a_printer(printer, 2);
9624         }
9625
9626         free_a_printer(&printer, 2);
9627
9628         return status;
9629 }
9630
9631 /****************************************************************
9632  _spoolss_DeletePrinterDataEx
9633 ****************************************************************/
9634
9635 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9636                                     struct spoolss_DeletePrinterDataEx *r)
9637 {
9638         POLICY_HND      *handle = r->in.handle;
9639         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9640         int             snum=0;
9641         WERROR          status = WERR_OK;
9642         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9643
9644         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9645
9646         if (!Printer) {
9647                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9648                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9649                 return WERR_BADFID;
9650         }
9651
9652         if (!get_printer_snum(p, handle, &snum, NULL))
9653                 return WERR_BADFID;
9654
9655         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9656                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9657                         "printer properties change denied by handle\n"));
9658                 return WERR_ACCESS_DENIED;
9659         }
9660
9661         if (!r->in.value_name || !r->in.key_name) {
9662                 return WERR_NOMEM;
9663         }
9664
9665         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9666         if (!W_ERROR_IS_OK(status))
9667                 return status;
9668
9669         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9670
9671         if ( W_ERROR_IS_OK(status) )
9672                 mod_a_printer( printer, 2 );
9673
9674         free_a_printer(&printer, 2);
9675
9676         return status;
9677 }
9678
9679 /********************************************************************
9680  * spoolss_enumprinterkey
9681  ********************************************************************/
9682
9683
9684 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9685 {
9686         fstring         key;
9687         fstring         *keynames = NULL;
9688         uint16          *enumkeys = NULL;
9689         int             num_keys;
9690         int             printerkey_len;
9691         POLICY_HND      *handle = &q_u->handle;
9692         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9693         NT_PRINTER_DATA *data;
9694         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9695         int             snum = 0;
9696         WERROR          status = WERR_BADFILE;
9697
9698
9699         DEBUG(4,("_spoolss_enumprinterkey\n"));
9700
9701         if (!Printer) {
9702                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9703                 return WERR_BADFID;
9704         }
9705
9706         if ( !get_printer_snum(p,handle, &snum, NULL) )
9707                 return WERR_BADFID;
9708
9709         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9710         if (!W_ERROR_IS_OK(status))
9711                 return status;
9712
9713         /* get the list of subkey names */
9714
9715         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9716         data = printer->info_2->data;
9717
9718         num_keys = get_printer_subkeys( data, key, &keynames );
9719
9720         if ( num_keys == -1 ) {
9721                 status = WERR_BADFILE;
9722                 goto done;
9723         }
9724
9725         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9726
9727         r_u->needed = printerkey_len*2;
9728
9729         if ( q_u->size < r_u->needed ) {
9730                 status = WERR_MORE_DATA;
9731                 goto done;
9732         }
9733
9734         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9735                 status = WERR_NOMEM;
9736                 goto done;
9737         }
9738
9739         status = WERR_OK;
9740
9741         if ( q_u->size < r_u->needed )
9742                 status = WERR_MORE_DATA;
9743
9744 done:
9745         free_a_printer( &printer, 2 );
9746         SAFE_FREE( keynames );
9747
9748         return status;
9749 }
9750
9751 /****************************************************************
9752  _spoolss_DeletePrinterKey
9753 ****************************************************************/
9754
9755 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9756                                  struct spoolss_DeletePrinterKey *r)
9757 {
9758         POLICY_HND              *handle = r->in.handle;
9759         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9760         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9761         int                     snum=0;
9762         WERROR                  status;
9763
9764         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9765
9766         if (!Printer) {
9767                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9768                         OUR_HANDLE(handle)));
9769                 return WERR_BADFID;
9770         }
9771
9772         /* if keyname == NULL, return error */
9773
9774         if ( !r->in.key_name )
9775                 return WERR_INVALID_PARAM;
9776
9777         if (!get_printer_snum(p, handle, &snum, NULL))
9778                 return WERR_BADFID;
9779
9780         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9781                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9782                         "printer properties change denied by handle\n"));
9783                 return WERR_ACCESS_DENIED;
9784         }
9785
9786         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9787         if (!W_ERROR_IS_OK(status))
9788                 return status;
9789
9790         /* delete the key and all subneys */
9791
9792         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9793
9794         if ( W_ERROR_IS_OK(status) )
9795                 status = mod_a_printer(printer, 2);
9796
9797         free_a_printer( &printer, 2 );
9798
9799         return status;
9800 }
9801
9802
9803 /********************************************************************
9804  * spoolss_enumprinterdataex
9805  ********************************************************************/
9806
9807 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9808 {
9809         POLICY_HND      *handle = &q_u->handle;
9810         uint32          in_size = q_u->size;
9811         uint32          num_entries,
9812                         needed;
9813         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9814         PRINTER_ENUM_VALUES     *enum_values = NULL;
9815         NT_PRINTER_DATA         *p_data;
9816         fstring         key;
9817         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9818         int             snum;
9819         WERROR          result;
9820         int             key_index;
9821         int             i;
9822         REGISTRY_VALUE  *val;
9823         char            *value_name;
9824         uint32          data_len;
9825
9826
9827         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9828
9829         if (!Printer) {
9830                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9831                 return WERR_BADFID;
9832         }
9833
9834         /*
9835          * first check for a keyname of NULL or "".  Win2k seems to send
9836          * this a lot and we should send back WERR_INVALID_PARAM
9837          * no need to spend time looking up the printer in this case.
9838          * --jerry
9839          */
9840
9841         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9842         if ( !strlen(key) ) {
9843                 result = WERR_INVALID_PARAM;
9844                 goto done;
9845         }
9846
9847         /* get the printer off of disk */
9848
9849         if (!get_printer_snum(p,handle, &snum, NULL))
9850                 return WERR_BADFID;
9851
9852         ZERO_STRUCT(printer);
9853         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9854         if (!W_ERROR_IS_OK(result))
9855                 return result;
9856
9857         /* now look for a match on the key name */
9858
9859         p_data = printer->info_2->data;
9860
9861         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9862         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9863         {
9864                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9865                 result = WERR_INVALID_PARAM;
9866                 goto done;
9867         }
9868
9869         result = WERR_OK;
9870         needed = 0;
9871
9872         /* allocate the memory for the array of pointers -- if necessary */
9873
9874         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9875         if ( num_entries )
9876         {
9877                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9878                 {
9879                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9880                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9881                         result = WERR_NOMEM;
9882                         goto done;
9883                 }
9884
9885                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9886         }
9887
9888         /*
9889          * loop through all params and build the array to pass
9890          * back to the  client
9891          */
9892
9893         for ( i=0; i<num_entries; i++ )
9894         {
9895                 /* lookup the registry value */
9896
9897                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9898                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9899
9900                 /* copy the data */
9901
9902                 value_name = regval_name( val );
9903                 init_unistr( &enum_values[i].valuename, value_name );
9904                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9905                 enum_values[i].type      = regval_type( val );
9906
9907                 data_len = regval_size( val );
9908                 if ( data_len ) {
9909                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9910                         {
9911                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9912                                         data_len ));
9913                                 result = WERR_NOMEM;
9914                                 goto done;
9915                         }
9916                 }
9917                 enum_values[i].data_len = data_len;
9918
9919                 /* keep track of the size of the array in bytes */
9920
9921                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9922         }
9923
9924         /* housekeeping information in the reply */
9925
9926         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9927          * the hand marshalled container size is a multiple
9928          * of 4 bytes for RPC alignment.
9929          */
9930
9931         if (needed % 4) {
9932                 needed += 4-(needed % 4);
9933         }
9934
9935         r_u->needed     = needed;
9936         r_u->returned   = num_entries;
9937
9938         if (needed > in_size) {
9939                 result = WERR_MORE_DATA;
9940                 goto done;
9941         }
9942
9943         /* copy data into the reply */
9944
9945         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9946            response buffer size is != the offered buffer size
9947
9948                 r_u->ctr.size           = r_u->needed;
9949         */
9950         r_u->ctr.size           = in_size;
9951
9952         r_u->ctr.size_of_array  = r_u->returned;
9953         r_u->ctr.values         = enum_values;
9954
9955 done:
9956         if ( printer )
9957         free_a_printer(&printer, 2);
9958
9959         return result;
9960 }
9961
9962 /****************************************************************************
9963 ****************************************************************************/
9964
9965 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9966                                                  const char *servername,
9967                                                  const char *environment,
9968                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9969 {
9970         WERROR werr;
9971         char *path = NULL;
9972
9973         werr = compose_spoolss_server_path(mem_ctx,
9974                                            servername,
9975                                            environment,
9976                                            SPOOLSS_PRTPROCS_PATH,
9977                                            &path);
9978         if (!W_ERROR_IS_OK(werr)) {
9979                 return werr;
9980         }
9981
9982         DEBUG(4,("print processor directory: [%s]\n", path));
9983
9984         r->directory_name = path;
9985
9986         return WERR_OK;
9987 }
9988
9989 /****************************************************************
9990  _spoolss_GetPrintProcessorDirectory
9991 ****************************************************************/
9992
9993 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9994                                            struct spoolss_GetPrintProcessorDirectory *r)
9995 {
9996         WERROR result;
9997
9998         /* that's an [in out] buffer */
9999
10000         if (!r->in.buffer && (r->in.offered != 0)) {
10001                 return WERR_INVALID_PARAM;
10002         }
10003
10004         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10005                 r->in.level));
10006
10007         *r->out.needed = 0;
10008
10009         /* r->in.level is ignored */
10010
10011         result = getprintprocessordirectory_level_1(p->mem_ctx,
10012                                                     r->in.server,
10013                                                     r->in.environment,
10014                                                     &r->out.info->info1);
10015         if (!W_ERROR_IS_OK(result)) {
10016                 TALLOC_FREE(r->out.info);
10017                 return result;
10018         }
10019
10020         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
10021                                                r->out.info, r->in.level);
10022         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10023
10024         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10025 }
10026
10027 /*******************************************************************
10028  ********************************************************************/
10029
10030 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10031                                const char *dllname)
10032 {
10033         enum ndr_err_code ndr_err;
10034         struct spoolss_MonitorUi ui;
10035
10036         ui.dll_name = dllname;
10037
10038         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
10039                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10040         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10041                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10042         }
10043         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10044 }
10045
10046 /*******************************************************************
10047  Streams the monitor UI DLL name in UNICODE
10048 *******************************************************************/
10049
10050 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10051                                NT_USER_TOKEN *token, DATA_BLOB *in,
10052                                DATA_BLOB *out, uint32_t *needed)
10053 {
10054         const char *dllname = "tcpmonui.dll";
10055
10056         *needed = (strlen(dllname)+1) * 2;
10057
10058         if (out->length < *needed) {
10059                 return WERR_INSUFFICIENT_BUFFER;
10060         }
10061
10062         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10063                 return WERR_NOMEM;
10064         }
10065
10066         return WERR_OK;
10067 }
10068
10069 /*******************************************************************
10070  ********************************************************************/
10071
10072 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10073                              struct spoolss_PortData1 *port1,
10074                              const DATA_BLOB *buf)
10075 {
10076         enum ndr_err_code ndr_err;
10077         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
10078                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10079         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10080                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10081         }
10082         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10083 }
10084
10085 /*******************************************************************
10086  ********************************************************************/
10087
10088 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10089                              struct spoolss_PortData2 *port2,
10090                              const DATA_BLOB *buf)
10091 {
10092         enum ndr_err_code ndr_err;
10093         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
10094                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10095         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10096                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10097         }
10098         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10099 }
10100
10101 /*******************************************************************
10102  Create a new TCP/IP port
10103 *******************************************************************/
10104
10105 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10106                              NT_USER_TOKEN *token, DATA_BLOB *in,
10107                              DATA_BLOB *out, uint32_t *needed)
10108 {
10109         struct spoolss_PortData1 port1;
10110         struct spoolss_PortData2 port2;
10111         char *device_uri = NULL;
10112         uint32_t version;
10113
10114         const char *portname;
10115         const char *hostaddress;
10116         const char *queue;
10117         uint32_t port_number;
10118         uint32_t protocol;
10119
10120         /* peek for spoolss_PortData version */
10121
10122         if (!in || (in->length < (128 + 4))) {
10123                 return WERR_GENERAL_FAILURE;
10124         }
10125
10126         version = IVAL(in->data, 128);
10127
10128         switch (version) {
10129                 case 1:
10130                         ZERO_STRUCT(port1);
10131
10132                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10133                                 return WERR_NOMEM;
10134                         }
10135
10136                         portname        = port1.portname;
10137                         hostaddress     = port1.hostaddress;
10138                         queue           = port1.queue;
10139                         protocol        = port1.protocol;
10140                         port_number     = port1.port_number;
10141
10142                         break;
10143                 case 2:
10144                         ZERO_STRUCT(port2);
10145
10146                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10147                                 return WERR_NOMEM;
10148                         }
10149
10150                         portname        = port2.portname;
10151                         hostaddress     = port2.hostaddress;
10152                         queue           = port2.queue;
10153                         protocol        = port2.protocol;
10154                         port_number     = port2.port_number;
10155
10156                         break;
10157                 default:
10158                         DEBUG(1,("xcvtcp_addport: "
10159                                 "unknown version of port_data: %d\n", version));
10160                         return WERR_UNKNOWN_PORT;
10161         }
10162
10163         /* create the device URI and call the add_port_hook() */
10164
10165         switch (protocol) {
10166         case PROTOCOL_RAWTCP_TYPE:
10167                 device_uri = talloc_asprintf(mem_ctx,
10168                                 "socket://%s:%d/", hostaddress,
10169                                 port_number);
10170                 break;
10171
10172         case PROTOCOL_LPR_TYPE:
10173                 device_uri = talloc_asprintf(mem_ctx,
10174                         "lpr://%s/%s", hostaddress, queue );
10175                 break;
10176
10177         default:
10178                 return WERR_UNKNOWN_PORT;
10179         }
10180
10181         if (!device_uri) {
10182                 return WERR_NOMEM;
10183         }
10184
10185         return add_port_hook(mem_ctx, token, portname, device_uri);
10186 }
10187
10188 /*******************************************************************
10189 *******************************************************************/
10190
10191 struct xcv_api_table xcvtcp_cmds[] = {
10192         { "MonitorUI",  xcvtcp_monitorui },
10193         { "AddPort",    xcvtcp_addport},
10194         { NULL,         NULL }
10195 };
10196
10197 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10198                                      NT_USER_TOKEN *token, const char *command,
10199                                      DATA_BLOB *inbuf,
10200                                      DATA_BLOB *outbuf,
10201                                      uint32_t *needed )
10202 {
10203         int i;
10204
10205         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10206
10207         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10208                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10209                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10210         }
10211
10212         return WERR_BADFUNC;
10213 }
10214
10215 /*******************************************************************
10216 *******************************************************************/
10217 #if 0   /* don't support management using the "Local Port" monitor */
10218
10219 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10220                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10221                                  DATA_BLOB *out, uint32_t *needed)
10222 {
10223         const char *dllname = "localui.dll";
10224
10225         *needed = (strlen(dllname)+1) * 2;
10226
10227         if (out->length < *needed) {
10228                 return WERR_INSUFFICIENT_BUFFER;
10229         }
10230
10231         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10232                 return WERR_NOMEM;
10233         }
10234
10235         return WERR_OK;
10236 }
10237
10238 /*******************************************************************
10239 *******************************************************************/
10240
10241 struct xcv_api_table xcvlocal_cmds[] = {
10242         { "MonitorUI",  xcvlocal_monitorui },
10243         { NULL,         NULL }
10244 };
10245 #else
10246 struct xcv_api_table xcvlocal_cmds[] = {
10247         { NULL,         NULL }
10248 };
10249 #endif
10250
10251
10252
10253 /*******************************************************************
10254 *******************************************************************/
10255
10256 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10257                                        NT_USER_TOKEN *token, const char *command,
10258                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10259                                        uint32_t *needed)
10260 {
10261         int i;
10262
10263         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10264
10265         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10266                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10267                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10268         }
10269         return WERR_BADFUNC;
10270 }
10271
10272 /****************************************************************
10273  _spoolss_XcvData
10274 ****************************************************************/
10275
10276 WERROR _spoolss_XcvData(pipes_struct *p,
10277                         struct spoolss_XcvData *r)
10278 {
10279         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10280         DATA_BLOB out_data = data_blob_null;
10281         WERROR werror;
10282
10283         if (!Printer) {
10284                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10285                         OUR_HANDLE(r->in.handle)));
10286                 return WERR_BADFID;
10287         }
10288
10289         /* Has to be a handle to the TCP/IP port monitor */
10290
10291         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10292                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10293                 return WERR_BADFID;
10294         }
10295
10296         /* requires administrative access to the server */
10297
10298         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10299                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10300                 return WERR_ACCESS_DENIED;
10301         }
10302
10303         /* Allocate the outgoing buffer */
10304
10305         if (r->in.out_data_size) {
10306                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10307                 if (out_data.data == NULL) {
10308                         return WERR_NOMEM;
10309                 }
10310         }
10311
10312         switch ( Printer->printer_type ) {
10313         case SPLHND_PORTMON_TCP:
10314                 werror = process_xcvtcp_command(p->mem_ctx,
10315                                                 p->server_info->ptok,
10316                                                 r->in.function_name,
10317                                                 &r->in.in_data, &out_data,
10318                                                 r->out.needed);
10319                 break;
10320         case SPLHND_PORTMON_LOCAL:
10321                 werror = process_xcvlocal_command(p->mem_ctx,
10322                                                   p->server_info->ptok,
10323                                                   r->in.function_name,
10324                                                   &r->in.in_data, &out_data,
10325                                                   r->out.needed);
10326                 break;
10327         default:
10328                 werror = WERR_INVALID_PRINT_MONITOR;
10329         }
10330
10331         if (!W_ERROR_IS_OK(werror)) {
10332                 return werror;
10333         }
10334
10335         *r->out.status_code = 0;
10336
10337         memcpy(r->out.out_data, out_data.data, out_data.length);
10338
10339         return WERR_OK;
10340 }
10341
10342 /****************************************************************
10343  _spoolss_AddPrintProcessor
10344 ****************************************************************/
10345
10346 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10347                                   struct spoolss_AddPrintProcessor *r)
10348 {
10349         /* for now, just indicate success and ignore the add.  We'll
10350            automatically set the winprint processor for printer
10351            entries later.  Used to debug the LexMark Optra S 1855 PCL
10352            driver --jerry */
10353
10354         return WERR_OK;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_AddPrinter
10359 ****************************************************************/
10360
10361 WERROR _spoolss_AddPrinter(pipes_struct *p,
10362                            struct spoolss_AddPrinter *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_GetPrinter
10370 ****************************************************************/
10371
10372 WERROR _spoolss_GetPrinter(pipes_struct *p,
10373                            struct spoolss_GetPrinter *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_GetPrinterDriver
10381 ****************************************************************/
10382
10383 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10384                                  struct spoolss_GetPrinterDriver *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_ReadPrinter
10392 ****************************************************************/
10393
10394 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10395                             struct spoolss_ReadPrinter *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_GetPrinterData
10403 ****************************************************************/
10404
10405 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10406                                struct spoolss_GetPrinterData *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_SetPrinterData
10414 ****************************************************************/
10415
10416 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10417                                struct spoolss_SetPrinterData *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_WaitForPrinterChange
10425 ****************************************************************/
10426
10427 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10428                                      struct spoolss_WaitForPrinterChange *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_AddPort
10436 ****************************************************************/
10437
10438 WERROR _spoolss_AddPort(pipes_struct *p,
10439                         struct spoolss_AddPort *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_ConfigurePort
10447 ****************************************************************/
10448
10449 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10450                               struct spoolss_ConfigurePort *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_DeletePort
10458 ****************************************************************/
10459
10460 WERROR _spoolss_DeletePort(pipes_struct *p,
10461                            struct spoolss_DeletePort *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_CreatePrinterIC
10469 ****************************************************************/
10470
10471 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10472                                 struct spoolss_CreatePrinterIC *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_PlayGDIScriptOnPrinterIC
10480 ****************************************************************/
10481
10482 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10483                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_DeletePrinterIC
10491 ****************************************************************/
10492
10493 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10494                                 struct spoolss_DeletePrinterIC *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_AddPrinterConnection
10502 ****************************************************************/
10503
10504 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10505                                      struct spoolss_AddPrinterConnection *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_DeletePrinterConnection
10513 ****************************************************************/
10514
10515 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10516                                         struct spoolss_DeletePrinterConnection *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_PrinterMessageBox
10524 ****************************************************************/
10525
10526 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10527                                   struct spoolss_PrinterMessageBox *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_AddMonitor
10535 ****************************************************************/
10536
10537 WERROR _spoolss_AddMonitor(pipes_struct *p,
10538                            struct spoolss_AddMonitor *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_DeleteMonitor
10546 ****************************************************************/
10547
10548 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10549                               struct spoolss_DeleteMonitor *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_DeletePrintProcessor
10557 ****************************************************************/
10558
10559 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10560                                      struct spoolss_DeletePrintProcessor *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_AddPrintProvidor
10568 ****************************************************************/
10569
10570 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10571                                  struct spoolss_AddPrintProvidor *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_DeletePrintProvidor
10579 ****************************************************************/
10580
10581 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10582                                     struct spoolss_DeletePrintProvidor *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_FindFirstPrinterChangeNotification
10590 ****************************************************************/
10591
10592 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10593                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_FindNextPrinterChangeNotification
10601 ****************************************************************/
10602
10603 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10604                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10612 ****************************************************************/
10613
10614 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10615                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_ReplyOpenPrinter
10623 ****************************************************************/
10624
10625 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10626                                  struct spoolss_ReplyOpenPrinter *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_RouterReplyPrinter
10634 ****************************************************************/
10635
10636 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10637                                    struct spoolss_RouterReplyPrinter *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_ReplyClosePrinter
10645 ****************************************************************/
10646
10647 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10648                                   struct spoolss_ReplyClosePrinter *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_AddPortEx
10656 ****************************************************************/
10657
10658 WERROR _spoolss_AddPortEx(pipes_struct *p,
10659                           struct spoolss_AddPortEx *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_RouterFindFirstPrinterChangeNotification
10667 ****************************************************************/
10668
10669 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10670                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10671 {
10672         p->rng_fault_state = true;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_SpoolerInit
10678 ****************************************************************/
10679
10680 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10681                             struct spoolss_SpoolerInit *r)
10682 {
10683         p->rng_fault_state = true;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_ResetPrinterEx
10689 ****************************************************************/
10690
10691 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10692                                struct spoolss_ResetPrinterEx *r)
10693 {
10694         p->rng_fault_state = true;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_RouterReplyPrinterEx
10700 ****************************************************************/
10701
10702 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10703                                      struct spoolss_RouterReplyPrinterEx *r)
10704 {
10705         p->rng_fault_state = true;
10706         return WERR_NOT_SUPPORTED;
10707 }
10708
10709 /****************************************************************
10710  _spoolss_44
10711 ****************************************************************/
10712
10713 WERROR _spoolss_44(pipes_struct *p,
10714                    struct spoolss_44 *r)
10715 {
10716         p->rng_fault_state = true;
10717         return WERR_NOT_SUPPORTED;
10718 }
10719
10720 /****************************************************************
10721  _spoolss_47
10722 ****************************************************************/
10723
10724 WERROR _spoolss_47(pipes_struct *p,
10725                    struct spoolss_47 *r)
10726 {
10727         p->rng_fault_state = true;
10728         return WERR_NOT_SUPPORTED;
10729 }
10730
10731 /****************************************************************
10732  _spoolss_EnumPrinterData
10733 ****************************************************************/
10734
10735 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10736                                 struct spoolss_EnumPrinterData *r)
10737 {
10738         p->rng_fault_state = true;
10739         return WERR_NOT_SUPPORTED;
10740 }
10741
10742 /****************************************************************
10743  _spoolss_4a
10744 ****************************************************************/
10745
10746 WERROR _spoolss_4a(pipes_struct *p,
10747                    struct spoolss_4a *r)
10748 {
10749         p->rng_fault_state = true;
10750         return WERR_NOT_SUPPORTED;
10751 }
10752
10753 /****************************************************************
10754  _spoolss_4b
10755 ****************************************************************/
10756
10757 WERROR _spoolss_4b(pipes_struct *p,
10758                    struct spoolss_4b *r)
10759 {
10760         p->rng_fault_state = true;
10761         return WERR_NOT_SUPPORTED;
10762 }
10763
10764 /****************************************************************
10765  _spoolss_4c
10766 ****************************************************************/
10767
10768 WERROR _spoolss_4c(pipes_struct *p,
10769                    struct spoolss_4c *r)
10770 {
10771         p->rng_fault_state = true;
10772         return WERR_NOT_SUPPORTED;
10773 }
10774
10775 /****************************************************************
10776  _spoolss_EnumPrinterDataEx
10777 ****************************************************************/
10778
10779 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10780                                   struct spoolss_EnumPrinterDataEx *r)
10781 {
10782         p->rng_fault_state = true;
10783         return WERR_NOT_SUPPORTED;
10784 }
10785
10786 /****************************************************************
10787  _spoolss_EnumPrinterKey
10788 ****************************************************************/
10789
10790 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10791                                struct spoolss_EnumPrinterKey *r)
10792 {
10793         p->rng_fault_state = true;
10794         return WERR_NOT_SUPPORTED;
10795 }
10796
10797 /****************************************************************
10798  _spoolss_53
10799 ****************************************************************/
10800
10801 WERROR _spoolss_53(pipes_struct *p,
10802                    struct spoolss_53 *r)
10803 {
10804         p->rng_fault_state = true;
10805         return WERR_NOT_SUPPORTED;
10806 }
10807
10808 /****************************************************************
10809  _spoolss_55
10810 ****************************************************************/
10811
10812 WERROR _spoolss_55(pipes_struct *p,
10813                    struct spoolss_55 *r)
10814 {
10815         p->rng_fault_state = true;
10816         return WERR_NOT_SUPPORTED;
10817 }
10818
10819 /****************************************************************
10820  _spoolss_56
10821 ****************************************************************/
10822
10823 WERROR _spoolss_56(pipes_struct *p,
10824                    struct spoolss_56 *r)
10825 {
10826         p->rng_fault_state = true;
10827         return WERR_NOT_SUPPORTED;
10828 }
10829
10830 /****************************************************************
10831  _spoolss_57
10832 ****************************************************************/
10833
10834 WERROR _spoolss_57(pipes_struct *p,
10835                    struct spoolss_57 *r)
10836 {
10837         p->rng_fault_state = true;
10838         return WERR_NOT_SUPPORTED;
10839 }
10840
10841 /****************************************************************
10842  _spoolss_5a
10843 ****************************************************************/
10844
10845 WERROR _spoolss_5a(pipes_struct *p,
10846                    struct spoolss_5a *r)
10847 {
10848         p->rng_fault_state = true;
10849         return WERR_NOT_SUPPORTED;
10850 }
10851
10852 /****************************************************************
10853  _spoolss_5b
10854 ****************************************************************/
10855
10856 WERROR _spoolss_5b(pipes_struct *p,
10857                    struct spoolss_5b *r)
10858 {
10859         p->rng_fault_state = true;
10860         return WERR_NOT_SUPPORTED;
10861 }
10862
10863 /****************************************************************
10864  _spoolss_5c
10865 ****************************************************************/
10866
10867 WERROR _spoolss_5c(pipes_struct *p,
10868                    struct spoolss_5c *r)
10869 {
10870         p->rng_fault_state = true;
10871         return WERR_NOT_SUPPORTED;
10872 }
10873
10874 /****************************************************************
10875  _spoolss_5d
10876 ****************************************************************/
10877
10878 WERROR _spoolss_5d(pipes_struct *p,
10879                    struct spoolss_5d *r)
10880 {
10881         p->rng_fault_state = true;
10882         return WERR_NOT_SUPPORTED;
10883 }
10884
10885 /****************************************************************
10886  _spoolss_5e
10887 ****************************************************************/
10888
10889 WERROR _spoolss_5e(pipes_struct *p,
10890                    struct spoolss_5e *r)
10891 {
10892         p->rng_fault_state = true;
10893         return WERR_NOT_SUPPORTED;
10894 }
10895
10896 /****************************************************************
10897  _spoolss_5f
10898 ****************************************************************/
10899
10900 WERROR _spoolss_5f(pipes_struct *p,
10901                    struct spoolss_5f *r)
10902 {
10903         p->rng_fault_state = true;
10904         return WERR_NOT_SUPPORTED;
10905 }
10906