s3-spoolss: use macros for _spoolss_EnumMonitors.
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32         ((info)?ndr_size_##fn(info, level, ic, 0):0)
33
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
36
37 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
38
39
40 extern userdom_struct current_user_info;
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_RPC_SRV
44
45 #ifndef MAX_OPEN_PRINTER_EXS
46 #define MAX_OPEN_PRINTER_EXS 50
47 #endif
48
49 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
50 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
51
52 struct table_node {
53         const char    *long_archi;
54         const char    *short_archi;
55         int     version;
56 };
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32 counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32 smb_connections=0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected==True) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected=False;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
231 {
232         Printer_entry *find_printer = NULL;
233
234         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
235                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
236                 return NULL;
237         }
238
239         return find_printer;
240 }
241
242 /****************************************************************************
243  Close printer index by handle.
244 ****************************************************************************/
245
246 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
247 {
248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249
250         if (!Printer) {
251                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
252                 return False;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return True;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
265 {
266         char *cmd = lp_deleteprinter_cmd();
267         char *command = NULL;
268         int ret;
269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
270         bool is_print_op = False;
271
272         /* can't fail if we don't try */
273
274         if ( !*cmd )
275                 return WERR_OK;
276
277         command = talloc_asprintf(ctx,
278                         "%s \"%s\"",
279                         cmd, sharename);
280         if (!command) {
281                 return WERR_NOMEM;
282         }
283         if ( token )
284                 is_print_op = user_has_privileges( token, &se_printop );
285
286         DEBUG(10,("Running [%s]\n", command));
287
288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290         if ( is_print_op )
291                 become_root();
292
293         if ( (ret = smbrun(command, NULL)) == 0 ) {
294                 /* Tell everyone we updated smb.conf. */
295                 message_send_all(smbd_messaging_context(),
296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
297         }
298
299         if ( is_print_op )
300                 unbecome_root();
301
302         /********** END SePrintOperatorPrivlege BLOCK **********/
303
304         DEBUGADD(10,("returned [%d]\n", ret));
305
306         TALLOC_FREE(command);
307
308         if (ret != 0)
309                 return WERR_BADFID; /* What to return here? */
310
311         /* go ahead and re-read the services immediately */
312         reload_services( False );
313
314         if ( lp_servicenumber( sharename )  < 0 )
315                 return WERR_ACCESS_DENIED;
316
317         return WERR_OK;
318 }
319
320 /****************************************************************************
321  Delete a printer given a handle.
322 ****************************************************************************/
323
324 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
325 {
326         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
327
328         if (!Printer) {
329                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
330                 return WERR_BADFID;
331         }
332
333         /*
334          * It turns out that Windows allows delete printer on a handle
335          * opened by an admin user, then used on a pipe handle created
336          * by an anonymous user..... but they're working on security.... riiight !
337          * JRA.
338          */
339
340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
341                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
342                 return WERR_ACCESS_DENIED;
343         }
344
345         /* this does not need a become root since the access check has been
346            done on the handle already */
347
348         if (del_a_printer( Printer->sharename ) != 0) {
349                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
350                 return WERR_BADFID;
351         }
352
353         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
354                                    Printer->sharename );
355 }
356
357 /****************************************************************************
358  Return the snum of a printer corresponding to an handle.
359 ****************************************************************************/
360
361 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
362                              struct share_params **params)
363 {
364         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368                 return False;
369         }
370
371         switch (Printer->printer_type) {
372                 case SPLHND_PRINTER:
373                         DEBUG(4,("short name:%s\n", Printer->sharename));
374                         *number = print_queue_snum(Printer->sharename);
375                         return (*number != -1);
376                 case SPLHND_SERVER:
377                         return False;
378                 default:
379                         return False;
380         }
381 }
382
383 /****************************************************************************
384  Set printer handle type.
385  Check if it's \\server or \\server\printer
386 ****************************************************************************/
387
388 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
389 {
390         DEBUG(3,("Setting printer type=%s\n", handlename));
391
392         if ( strlen(handlename) < 3 ) {
393                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
394                 return False;
395         }
396
397         /* it's a print server */
398         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
399                 DEBUGADD(4,("Printer is a print server\n"));
400                 Printer->printer_type = SPLHND_SERVER;
401         }
402         /* it's a printer (set_printer_hnd_name() will handle port monitors */
403         else {
404                 DEBUGADD(4,("Printer is a printer\n"));
405                 Printer->printer_type = SPLHND_PRINTER;
406         }
407
408         return True;
409 }
410
411 /****************************************************************************
412  Set printer handle name..  Accept names like \\server, \\server\printer,
413  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
414  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
415  XcvDataPort() interface.
416 ****************************************************************************/
417
418 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
419 {
420         int snum;
421         int n_services=lp_numservices();
422         char *aprinter, *printername;
423         const char *servername;
424         fstring sname;
425         bool found=False;
426         NT_PRINTER_INFO_LEVEL *printer = NULL;
427         WERROR result;
428
429         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
430
431         aprinter = handlename;
432         if ( *handlename == '\\' ) {
433                 servername = canon_servername(handlename);
434                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
435                         *aprinter = '\0';
436                         aprinter++;
437                 }
438         } else {
439                 servername = "";
440         }
441
442         /* save the servername to fill in replies on this handle */
443
444         if ( !is_myname_or_ipaddr( servername ) )
445                 return False;
446
447         fstrcpy( Printer->servername, servername );
448
449         if ( Printer->printer_type == SPLHND_SERVER )
450                 return True;
451
452         if ( Printer->printer_type != SPLHND_PRINTER )
453                 return False;
454
455         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
456
457         /* check for the Port Monitor Interface */
458
459         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
460                 Printer->printer_type = SPLHND_PORTMON_TCP;
461                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
462                 found = True;
463         }
464         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
465                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
466                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
467                 found = True;
468         }
469
470         /* Search all sharenames first as this is easier than pulling
471            the printer_info_2 off of disk. Don't use find_service() since
472            that calls out to map_username() */
473
474         /* do another loop to look for printernames */
475
476         for (snum=0; !found && snum<n_services; snum++) {
477
478                 /* no point going on if this is not a printer */
479
480                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
481                         continue;
482
483                 fstrcpy(sname, lp_servicename(snum));
484                 if ( strequal( aprinter, sname ) ) {
485                         found = True;
486                         break;
487                 }
488
489                 /* no point looking up the printer object if
490                    we aren't allowing printername != sharename */
491
492                 if ( lp_force_printername(snum) )
493                         continue;
494
495                 fstrcpy(sname, lp_servicename(snum));
496
497                 printer = NULL;
498
499                 /* This call doesn't fill in the location or comment from
500                  * a CUPS server for efficiency with large numbers of printers.
501                  * JRA.
502                  */
503
504                 result = get_a_printer_search( NULL, &printer, 2, sname );
505                 if ( !W_ERROR_IS_OK(result) ) {
506                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
507                                 sname, win_errstr(result)));
508                         continue;
509                 }
510
511                 /* printername is always returned as \\server\printername */
512                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
513                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
514                                 printer->info_2->printername));
515                         free_a_printer( &printer, 2);
516                         continue;
517                 }
518
519                 printername++;
520
521                 if ( strequal(printername, aprinter) ) {
522                         free_a_printer( &printer, 2);
523                         found = True;
524                         break;
525                 }
526
527                 DEBUGADD(10, ("printername: %s\n", printername));
528
529                 free_a_printer( &printer, 2);
530         }
531
532         free_a_printer( &printer, 2);
533
534         if ( !found ) {
535                 DEBUGADD(4,("Printer not found\n"));
536                 return False;
537         }
538
539         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
540
541         fstrcpy(Printer->sharename, sname);
542
543         return True;
544 }
545
546 /****************************************************************************
547  Find first available printer slot. creates a printer handle for you.
548  ****************************************************************************/
549
550 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
551 {
552         Printer_entry *new_printer;
553
554         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
555
556         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
557         if (new_printer == NULL) {
558                 return false;
559         }
560         talloc_set_destructor(new_printer, printer_entry_destructor);
561
562         if (!create_policy_hnd(p, hnd, new_printer)) {
563                 TALLOC_FREE(new_printer);
564                 return False;
565         }
566
567         /* Add to the internal list. */
568         DLIST_ADD(printers_list, new_printer);
569
570         new_printer->notify.option=NULL;
571
572         if (!set_printer_hnd_printertype(new_printer, name)) {
573                 close_printer_handle(p, hnd);
574                 return False;
575         }
576
577         if (!set_printer_hnd_name(new_printer, name)) {
578                 close_printer_handle(p, hnd);
579                 return False;
580         }
581
582         new_printer->access_granted = access_granted;
583
584         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585
586         return True;
587 }
588
589 /***************************************************************************
590  check to see if the client motify handle is monitoring the notification
591  given by (notify_type, notify_field).
592  **************************************************************************/
593
594 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
595                                       uint16 notify_field)
596 {
597         return True;
598 }
599
600 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
601                                 uint16 notify_field)
602 {
603         struct spoolss_NotifyOption *option = p->notify.option;
604         uint32 i, j;
605
606         /*
607          * Flags should always be zero when the change notify
608          * is registered by the client's spooler.  A user Win32 app
609          * might use the flags though instead of the NOTIFY_OPTION_INFO
610          * --jerry
611          */
612
613         if (!option) {
614                 return False;
615         }
616
617         if (p->notify.flags)
618                 return is_monitoring_event_flags(
619                         p->notify.flags, notify_type, notify_field);
620
621         for (i = 0; i < option->count; i++) {
622
623                 /* Check match for notify_type */
624
625                 if (option->types[i].type != notify_type)
626                         continue;
627
628                 /* Check match for field */
629
630                 for (j = 0; j < option->types[i].count; j++) {
631                         if (option->types[i].fields[j] == notify_field) {
632                                 return True;
633                         }
634                 }
635         }
636
637         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
638                    p->servername, p->sharename, notify_type, notify_field));
639
640         return False;
641 }
642
643 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
644         _data->data.integer[0] = _integer; \
645         _data->data.integer[1] = 0;
646
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
649         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
650         if (!_data->data.string.string) {\
651                 _data->data.string.size = 0; \
652         } \
653         _data->data.string.size = strlen_m_term(_p) * 2;
654
655 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
656         _data->data.devmode.devmode = _devmode;
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
659         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
660         if (!_data->data.sd.sd) { \
661                 _data->data.sd.sd_size = 0; \
662         } \
663         _data->data.sd.sd_size = _size;
664
665 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
666                                    struct tm *t,
667                                    const char **pp,
668                                    uint32_t *plen)
669 {
670         struct spoolss_Time st;
671         uint32_t len = 16;
672         char *p;
673
674         if (!init_systemtime(&st, t)) {
675                 return;
676         }
677
678         p = talloc_array(mem_ctx, char, len);
679         if (!p) {
680                 return;
681         }
682
683         /*
684          * Systemtime must be linearized as a set of UINT16's.
685          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
686          */
687
688         SSVAL(p, 0, st.year);
689         SSVAL(p, 2, st.month);
690         SSVAL(p, 4, st.day_of_week);
691         SSVAL(p, 6, st.day);
692         SSVAL(p, 8, st.hour);
693         SSVAL(p, 10, st.minute);
694         SSVAL(p, 12, st.second);
695         SSVAL(p, 14, st.millisecond);
696
697         *pp = p;
698         *plen = len;
699 }
700
701 /* Convert a notification message to a struct spoolss_Notify */
702
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704                              struct spoolss_Notify *data,
705                              TALLOC_CTX *mem_ctx)
706 {
707         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
708 }
709
710 static void notify_string(struct spoolss_notify_msg *msg,
711                           struct spoolss_Notify *data,
712                           TALLOC_CTX *mem_ctx)
713 {
714         /* The length of the message includes the trailing \0 */
715
716         data->data.string.size = msg->len * 2;
717         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
718         if (!data->data.string.string) {
719                 data->data.string.size = 0;
720                 return;
721         }
722 }
723
724 static void notify_system_time(struct spoolss_notify_msg *msg,
725                                struct spoolss_Notify *data,
726                                TALLOC_CTX *mem_ctx)
727 {
728         data->data.string.string = NULL;
729         data->data.string.size = 0;
730
731         if (msg->len != sizeof(time_t)) {
732                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
733                           msg->len));
734                 return;
735         }
736
737         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
738                                &data->data.string.string,
739                                &data->data.string.size);
740 }
741
742 struct notify2_message_table {
743         const char *name;
744         void (*fn)(struct spoolss_notify_msg *msg,
745                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
746 };
747
748 static struct notify2_message_table printer_notify_table[] = {
749         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
750         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
751         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
752         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
753         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
754         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
755         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
756         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
757         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
758         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
759         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
760         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
761         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
762         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
763         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
764         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
765         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
766         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
767         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 };
769
770 static struct notify2_message_table job_notify_table[] = {
771         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
772         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
773         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
774         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
775         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
776         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
777         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
778         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
779         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
780         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
781         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
782         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
783         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
784         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
785         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
786         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
787         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
788         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
789         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
790         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
791         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
792         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
793         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
794         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
795 };
796
797
798 /***********************************************************************
799  Allocate talloc context for container object
800  **********************************************************************/
801
802 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 {
804         if ( !ctr )
805                 return;
806
807         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808
809         return;
810 }
811
812 /***********************************************************************
813  release all allocated memory and zero out structure
814  **********************************************************************/
815
816 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
817 {
818         if ( !ctr )
819                 return;
820
821         if ( ctr->ctx )
822                 talloc_destroy(ctr->ctx);
823
824         ZERO_STRUCTP(ctr);
825
826         return;
827 }
828
829 /***********************************************************************
830  **********************************************************************/
831
832 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 {
834         if ( !ctr )
835                 return NULL;
836
837         return ctr->ctx;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 {
845         if ( !ctr || !ctr->msg_groups )
846                 return NULL;
847
848         if ( idx >= ctr->num_groups )
849                 return NULL;
850
851         return &ctr->msg_groups[idx];
852
853 }
854
855 /***********************************************************************
856  How many groups of change messages do we have ?
857  **********************************************************************/
858
859 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 {
861         if ( !ctr )
862                 return 0;
863
864         return ctr->num_groups;
865 }
866
867 /***********************************************************************
868  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
869  **********************************************************************/
870
871 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 {
873         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
874         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
875         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
876         int                             i, new_slot;
877
878         if ( !ctr || !msg )
879                 return 0;
880
881         /* loop over all groups looking for a matching printer name */
882
883         for ( i=0; i<ctr->num_groups; i++ ) {
884                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
885                         break;
886         }
887
888         /* add a new group? */
889
890         if ( i == ctr->num_groups ) {
891                 ctr->num_groups++;
892
893                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
894                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895                         return 0;
896                 }
897                 ctr->msg_groups = groups;
898
899                 /* clear the new entry and set the printer name */
900
901                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
902                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903         }
904
905         /* add the change messages; 'i' is the correct index now regardless */
906
907         msg_grp = &ctr->msg_groups[i];
908
909         msg_grp->num_msgs++;
910
911         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
912                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913                 return 0;
914         }
915         msg_grp->msgs = msg_list;
916
917         new_slot = msg_grp->num_msgs-1;
918         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919
920         /* need to allocate own copy of data */
921
922         if ( msg->len != 0 )
923                 msg_grp->msgs[new_slot].notify.data = (char *)
924                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
925
926         return ctr->num_groups;
927 }
928
929 /***********************************************************************
930  Send a change notication message on all handles which have a call
931  back registered
932  **********************************************************************/
933
934 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
935 {
936         Printer_entry            *p;
937         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
938         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
939         SPOOLSS_NOTIFY_MSG       *messages;
940         int                      sending_msg_count;
941
942         if ( !msg_group ) {
943                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944                 return;
945         }
946
947         messages = msg_group->msgs;
948
949         if ( !messages ) {
950                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951                 return;
952         }
953
954         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
955
956         /* loop over all printers */
957
958         for (p = printers_list; p; p = p->next) {
959                 struct spoolss_Notify *notifies;
960                 uint32_t count = 0;
961                 uint32_t id;
962                 int     i;
963
964                 /* Is there notification on this handle? */
965
966                 if ( !p->notify.client_connected )
967                         continue;
968
969                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
970
971                 /* For this printer?  Print servers always receive
972                    notifications. */
973
974                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
975                     ( !strequal(msg_group->printername, p->sharename) ) )
976                         continue;
977
978                 DEBUG(10,("Our printer\n"));
979
980                 /* allocate the max entries possible */
981
982                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
983                 if (!notifies) {
984                         return;
985                 }
986
987                 /* build the array of change notifications */
988
989                 sending_msg_count = 0;
990
991                 for ( i=0; i<msg_group->num_msgs; i++ ) {
992                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
993
994                         /* Are we monitoring this event? */
995
996                         if (!is_monitoring_event(p, msg->type, msg->field))
997                                 continue;
998
999                         sending_msg_count++;
1000
1001
1002                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1003                                 msg->type, msg->field, p->sharename));
1004
1005                         /*
1006                          * if the is a printer notification handle and not a job notification
1007                          * type, then set the id to 0.  Other wise just use what was specified
1008                          * in the message.
1009                          *
1010                          * When registering change notification on a print server handle
1011                          * we always need to send back the id (snum) matching the printer
1012                          * for which the change took place.  For change notify registered
1013                          * on a printer handle, this does not matter and the id should be 0.
1014                          *
1015                          * --jerry
1016                          */
1017
1018                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019                                 id = 0;
1020                         else
1021                                 id = msg->id;
1022
1023
1024                         /* Convert unix jobid to smb jobid */
1025
1026                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1027                                 id = sysjob_to_jobid(msg->id);
1028
1029                                 if (id == -1) {
1030                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1031                                         goto done;
1032                                 }
1033                         }
1034
1035                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1036
1037                         switch(msg->type) {
1038                         case PRINTER_NOTIFY_TYPE:
1039                                 if ( printer_notify_table[msg->field].fn )
1040                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1041                                 break;
1042
1043                         case JOB_NOTIFY_TYPE:
1044                                 if ( job_notify_table[msg->field].fn )
1045                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1046                                 break;
1047
1048                         default:
1049                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1050                                 goto done;
1051                         }
1052
1053                         count++;
1054                 }
1055
1056                 if ( sending_msg_count ) {
1057                         NTSTATUS status;
1058                         WERROR werr;
1059                         union spoolss_ReplyPrinterInfo info;
1060                         struct spoolss_NotifyInfo info0;
1061                         uint32_t reply_result;
1062
1063                         info0.version   = 0x2;
1064                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1065                         info0.count     = count;
1066                         info0.notifies  = notifies;
1067
1068                         info.info0 = &info0;
1069
1070                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1071                                                                      &p->notify.client_hnd,
1072                                                                      p->notify.change, /* color */
1073                                                                      p->notify.flags,
1074                                                                      &reply_result,
1075                                                                      0, /* reply_type, must be 0 */
1076                                                                      info,
1077                                                                      &werr);
1078                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1079                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1080                                         notify_cli_pipe->srv_name_slash,
1081                                         win_errstr(werr)));
1082                         }
1083                         switch (reply_result) {
1084                                 case 0:
1085                                         break;
1086                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1087                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1088                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1089                                         break;
1090                                 default:
1091                                         break;
1092                         }
1093                 }
1094         }
1095
1096 done:
1097         DEBUG(8,("send_notify2_changes: Exit...\n"));
1098         return;
1099 }
1100
1101 /***********************************************************************
1102  **********************************************************************/
1103
1104 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1105 {
1106
1107         uint32 tv_sec, tv_usec;
1108         size_t offset = 0;
1109
1110         /* Unpack message */
1111
1112         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1113                              msg->printer);
1114
1115         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1116                                 &tv_sec, &tv_usec,
1117                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1118
1119         if (msg->len == 0)
1120                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1121                            &msg->notify.value[0], &msg->notify.value[1]);
1122         else
1123                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1124                            &msg->len, &msg->notify.data);
1125
1126         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1127                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1128
1129         tv->tv_sec = tv_sec;
1130         tv->tv_usec = tv_usec;
1131
1132         if (msg->len == 0)
1133                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1134                           msg->notify.value[1]));
1135         else
1136                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1137
1138         return True;
1139 }
1140
1141 /********************************************************************
1142  Receive a notify2 message list
1143  ********************************************************************/
1144
1145 static void receive_notify2_message_list(struct messaging_context *msg,
1146                                          void *private_data,
1147                                          uint32_t msg_type,
1148                                          struct server_id server_id,
1149                                          DATA_BLOB *data)
1150 {
1151         size_t                  msg_count, i;
1152         char                    *buf = (char *)data->data;
1153         char                    *msg_ptr;
1154         size_t                  msg_len;
1155         SPOOLSS_NOTIFY_MSG      notify;
1156         SPOOLSS_NOTIFY_MSG_CTR  messages;
1157         int                     num_groups;
1158
1159         if (data->length < 4) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1161                 return;
1162         }
1163
1164         msg_count = IVAL(buf, 0);
1165         msg_ptr = buf + 4;
1166
1167         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168
1169         if (msg_count == 0) {
1170                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1171                 return;
1172         }
1173
1174         /* initialize the container */
1175
1176         ZERO_STRUCT( messages );
1177         notify_msg_ctr_init( &messages );
1178
1179         /*
1180          * build message groups for each printer identified
1181          * in a change_notify msg.  Remember that a PCN message
1182          * includes the handle returned for the srv_spoolss_replyopenprinter()
1183          * call.  Therefore messages are grouped according to printer handle.
1184          */
1185
1186         for ( i=0; i<msg_count; i++ ) {
1187                 struct timeval msg_tv;
1188
1189                 if (msg_ptr + 4 - buf > data->length) {
1190                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1191                         return;
1192                 }
1193
1194                 msg_len = IVAL(msg_ptr,0);
1195                 msg_ptr += 4;
1196
1197                 if (msg_ptr + msg_len - buf > data->length) {
1198                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1199                         return;
1200                 }
1201
1202                 /* unpack messages */
1203
1204                 ZERO_STRUCT( notify );
1205                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1206                 msg_ptr += msg_len;
1207
1208                 /* add to correct list in container */
1209
1210                 notify_msg_ctr_addmsg( &messages, &notify );
1211
1212                 /* free memory that might have been allocated by notify2_unpack_msg() */
1213
1214                 if ( notify.len != 0 )
1215                         SAFE_FREE( notify.notify.data );
1216         }
1217
1218         /* process each group of messages */
1219
1220         num_groups = notify_msg_ctr_numgroups( &messages );
1221         for ( i=0; i<num_groups; i++ )
1222                 send_notify2_changes( &messages, i );
1223
1224
1225         /* cleanup */
1226
1227         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228
1229         notify_msg_ctr_destroy( &messages );
1230
1231         return;
1232 }
1233
1234 /********************************************************************
1235  Send a message to ourself about new driver being installed
1236  so we can upgrade the information for each printer bound to this
1237  driver
1238  ********************************************************************/
1239
1240 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1241 {
1242         int len = strlen(drivername);
1243
1244         if (!len)
1245                 return False;
1246
1247         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1248                 drivername));
1249
1250         messaging_send_buf(smbd_messaging_context(), procid_self(),
1251                            MSG_PRINTER_DRVUPGRADE,
1252                            (uint8 *)drivername, len+1);
1253
1254         return True;
1255 }
1256
1257 /**********************************************************************
1258  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1259  over all printers, upgrading ones as necessary
1260  **********************************************************************/
1261
1262 void do_drv_upgrade_printer(struct messaging_context *msg,
1263                             void *private_data,
1264                             uint32_t msg_type,
1265                             struct server_id server_id,
1266                             DATA_BLOB *data)
1267 {
1268         fstring drivername;
1269         int snum;
1270         int n_services = lp_numservices();
1271         size_t len;
1272
1273         len = MIN(data->length,sizeof(drivername)-1);
1274         strncpy(drivername, (const char *)data->data, len);
1275
1276         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1277
1278         /* Iterate the printer list */
1279
1280         for (snum=0; snum<n_services; snum++)
1281         {
1282                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1283                 {
1284                         WERROR result;
1285                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1286
1287                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1288                         if (!W_ERROR_IS_OK(result))
1289                                 continue;
1290
1291                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1292                         {
1293                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1294
1295                                 /* all we care about currently is the change_id */
1296
1297                                 result = mod_a_printer(printer, 2);
1298                                 if (!W_ERROR_IS_OK(result)) {
1299                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1300                                                 win_errstr(result)));
1301                                 }
1302                         }
1303
1304                         free_a_printer(&printer, 2);
1305                 }
1306         }
1307
1308         /* all done */
1309 }
1310
1311 /********************************************************************
1312  Update the cache for all printq's with a registered client
1313  connection
1314  ********************************************************************/
1315
1316 void update_monitored_printq_cache( void )
1317 {
1318         Printer_entry *printer = printers_list;
1319         int snum;
1320
1321         /* loop through all printers and update the cache where
1322            client_connected == True */
1323         while ( printer )
1324         {
1325                 if ( (printer->printer_type == SPLHND_PRINTER)
1326                         && printer->notify.client_connected )
1327                 {
1328                         snum = print_queue_snum(printer->sharename);
1329                         print_queue_status( snum, NULL, NULL );
1330                 }
1331
1332                 printer = printer->next;
1333         }
1334
1335         return;
1336 }
1337 /********************************************************************
1338  Send a message to ourself about new driver being installed
1339  so we can upgrade the information for each printer bound to this
1340  driver
1341  ********************************************************************/
1342
1343 static bool srv_spoolss_reset_printerdata(char* drivername)
1344 {
1345         int len = strlen(drivername);
1346
1347         if (!len)
1348                 return False;
1349
1350         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351                 drivername));
1352
1353         messaging_send_buf(smbd_messaging_context(), procid_self(),
1354                            MSG_PRINTERDATA_INIT_RESET,
1355                            (uint8 *)drivername, len+1);
1356
1357         return True;
1358 }
1359
1360 /**********************************************************************
1361  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1362  over all printers, resetting printer data as neessary
1363  **********************************************************************/
1364
1365 void reset_all_printerdata(struct messaging_context *msg,
1366                            void *private_data,
1367                            uint32_t msg_type,
1368                            struct server_id server_id,
1369                            DATA_BLOB *data)
1370 {
1371         fstring drivername;
1372         int snum;
1373         int n_services = lp_numservices();
1374         size_t len;
1375
1376         len = MIN( data->length, sizeof(drivername)-1 );
1377         strncpy( drivername, (const char *)data->data, len );
1378
1379         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1380
1381         /* Iterate the printer list */
1382
1383         for ( snum=0; snum<n_services; snum++ )
1384         {
1385                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1386                 {
1387                         WERROR result;
1388                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1389
1390                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1391                         if ( !W_ERROR_IS_OK(result) )
1392                                 continue;
1393
1394                         /*
1395                          * if the printer is bound to the driver,
1396                          * then reset to the new driver initdata
1397                          */
1398
1399                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1400                         {
1401                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1402
1403                                 if ( !set_driver_init(printer, 2) ) {
1404                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1405                                                 printer->info_2->printername, printer->info_2->drivername));
1406                                 }
1407
1408                                 result = mod_a_printer( printer, 2 );
1409                                 if ( !W_ERROR_IS_OK(result) ) {
1410                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1411                                                 get_dos_error_msg(result)));
1412                                 }
1413                         }
1414
1415                         free_a_printer( &printer, 2 );
1416                 }
1417         }
1418
1419         /* all done */
1420
1421         return;
1422 }
1423
1424 /****************************************************************
1425  _spoolss_OpenPrinter
1426 ****************************************************************/
1427
1428 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1429                             struct spoolss_OpenPrinter *r)
1430 {
1431         struct spoolss_OpenPrinterEx e;
1432         WERROR werr;
1433
1434         ZERO_STRUCT(e.in.userlevel);
1435
1436         e.in.printername        = r->in.printername;
1437         e.in.datatype           = r->in.datatype;
1438         e.in.devmode_ctr        = r->in.devmode_ctr;
1439         e.in.access_mask        = r->in.access_mask;
1440         e.in.level              = 0;
1441
1442         e.out.handle            = r->out.handle;
1443
1444         werr = _spoolss_OpenPrinterEx(p, &e);
1445
1446         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1447                 /* OpenPrinterEx returns this for a bad
1448                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1449                  * instead.
1450                  */
1451                 werr = WERR_INVALID_PRINTER_NAME;
1452         }
1453
1454         return werr;
1455 }
1456
1457 /********************************************************************
1458  FIXME: temporary convert_devicemode_new function
1459  ********************************************************************/
1460
1461 static bool convert_devicemode_new(const char *printername,
1462                                    struct spoolss_DeviceMode *devmode,
1463                                    NT_DEVICEMODE **pp_nt_devmode)
1464 {
1465         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1466
1467         /*
1468          * Ensure nt_devmode is a valid pointer
1469          * as we will be overwriting it.
1470          */
1471
1472         if (nt_devmode == NULL) {
1473                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1474                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1475                         return false;
1476         }
1477
1478         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1479         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1480
1481         nt_devmode->specversion         = devmode->specversion;
1482         nt_devmode->driverversion       = devmode->driverversion;
1483         nt_devmode->size                = devmode->size;
1484         nt_devmode->fields              = devmode->fields;
1485         nt_devmode->orientation         = devmode->orientation;
1486         nt_devmode->papersize           = devmode->papersize;
1487         nt_devmode->paperlength         = devmode->paperlength;
1488         nt_devmode->paperwidth          = devmode->paperwidth;
1489         nt_devmode->scale               = devmode->scale;
1490         nt_devmode->copies              = devmode->copies;
1491         nt_devmode->defaultsource       = devmode->defaultsource;
1492         nt_devmode->printquality        = devmode->printquality;
1493         nt_devmode->color               = devmode->color;
1494         nt_devmode->duplex              = devmode->duplex;
1495         nt_devmode->yresolution         = devmode->yresolution;
1496         nt_devmode->ttoption            = devmode->ttoption;
1497         nt_devmode->collate             = devmode->collate;
1498
1499         nt_devmode->logpixels           = devmode->logpixels;
1500         nt_devmode->bitsperpel          = devmode->bitsperpel;
1501         nt_devmode->pelswidth           = devmode->pelswidth;
1502         nt_devmode->pelsheight          = devmode->pelsheight;
1503         nt_devmode->displayflags        = devmode->displayflags;
1504         nt_devmode->displayfrequency    = devmode->displayfrequency;
1505         nt_devmode->icmmethod           = devmode->icmmethod;
1506         nt_devmode->icmintent           = devmode->icmintent;
1507         nt_devmode->mediatype           = devmode->mediatype;
1508         nt_devmode->dithertype          = devmode->dithertype;
1509         nt_devmode->reserved1           = devmode->reserved1;
1510         nt_devmode->reserved2           = devmode->reserved2;
1511         nt_devmode->panningwidth        = devmode->panningwidth;
1512         nt_devmode->panningheight       = devmode->panningheight;
1513
1514         /*
1515          * Only change private and driverextra if the incoming devmode
1516          * has a new one. JRA.
1517          */
1518
1519         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1520                 SAFE_FREE(nt_devmode->nt_dev_private);
1521                 nt_devmode->driverextra = devmode->__driverextra_length;
1522                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1523                         return false;
1524                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1525         }
1526
1527         *pp_nt_devmode = nt_devmode;
1528
1529         return true;
1530 }
1531
1532 /****************************************************************
1533  _spoolss_OpenPrinterEx
1534 ****************************************************************/
1535
1536 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1537                               struct spoolss_OpenPrinterEx *r)
1538 {
1539         POLICY_HND              *handle = r->out.handle;
1540         char *name = CONST_DISCARD(char *, r->in.printername);
1541         int snum;
1542         Printer_entry *Printer=NULL;
1543
1544         if (!name) {
1545                 return WERR_INVALID_PARAM;
1546         }
1547
1548         /* some sanity check because you can open a printer or a print server */
1549         /* aka: \\server\printer or \\server */
1550
1551         DEBUGADD(3,("checking name: %s\n",name));
1552
1553         if (!open_printer_hnd(p, handle, name, 0)) {
1554                 ZERO_STRUCTP(r->out.handle);
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         Printer=find_printer_index_by_hnd(p, handle);
1559         if ( !Printer ) {
1560                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1561                         "handle we created for printer %s\n", name ));
1562                 close_printer_handle(p,handle);
1563                 ZERO_STRUCTP(r->out.handle);
1564                 return WERR_INVALID_PARAM;
1565         }
1566
1567         /*
1568          * First case: the user is opening the print server:
1569          *
1570          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1571          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1572          *
1573          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1574          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1575          * or if the user is listed in the smb.conf printer admin parameter.
1576          *
1577          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1578          * client view printer folder, but does not show the MSAPW.
1579          *
1580          * Note: this test needs code to check access rights here too. Jeremy
1581          * could you look at this?
1582          *
1583          * Second case: the user is opening a printer:
1584          * NT doesn't let us connect to a printer if the connecting user
1585          * doesn't have print permission.
1586          *
1587          * Third case: user is opening a Port Monitor
1588          * access checks same as opening a handle to the print server.
1589          */
1590
1591         switch (Printer->printer_type )
1592         {
1593         case SPLHND_SERVER:
1594         case SPLHND_PORTMON_TCP:
1595         case SPLHND_PORTMON_LOCAL:
1596                 /* Printserver handles use global struct... */
1597
1598                 snum = -1;
1599
1600                 /* Map standard access rights to object specific access rights */
1601
1602                 se_map_standard(&r->in.access_mask,
1603                                 &printserver_std_mapping);
1604
1605                 /* Deny any object specific bits that don't apply to print
1606                    servers (i.e printer and job specific bits) */
1607
1608                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1609
1610                 if (r->in.access_mask &
1611                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1612                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1613                         close_printer_handle(p, handle);
1614                         ZERO_STRUCTP(r->out.handle);
1615                         return WERR_ACCESS_DENIED;
1616                 }
1617
1618                 /* Allow admin access */
1619
1620                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1621                 {
1622                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1623
1624                         if (!lp_ms_add_printer_wizard()) {
1625                                 close_printer_handle(p, handle);
1626                                 ZERO_STRUCTP(r->out.handle);
1627                                 return WERR_ACCESS_DENIED;
1628                         }
1629
1630                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1631                            and not a printer admin, then fail */
1632
1633                         if ((p->server_info->utok.uid != 0) &&
1634                             !user_has_privileges(p->server_info->ptok,
1635                                                  &se_printop ) &&
1636                             !token_contains_name_in_list(
1637                                     uidtoname(p->server_info->utok.uid),
1638                                     NULL, NULL,
1639                                     p->server_info->ptok,
1640                                     lp_printer_admin(snum))) {
1641                                 close_printer_handle(p, handle);
1642                                 ZERO_STRUCTP(r->out.handle);
1643                                 return WERR_ACCESS_DENIED;
1644                         }
1645
1646                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1647                 }
1648                 else
1649                 {
1650                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1651                 }
1652
1653                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1654                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1655
1656                 /* We fall through to return WERR_OK */
1657                 break;
1658
1659         case SPLHND_PRINTER:
1660                 /* NT doesn't let us connect to a printer if the connecting user
1661                    doesn't have print permission.  */
1662
1663                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1664                         close_printer_handle(p, handle);
1665                         ZERO_STRUCTP(r->out.handle);
1666                         return WERR_BADFID;
1667                 }
1668
1669                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1670
1671                 /* map an empty access mask to the minimum access mask */
1672                 if (r->in.access_mask == 0x0)
1673                         r->in.access_mask = PRINTER_ACCESS_USE;
1674
1675                 /*
1676                  * If we are not serving the printer driver for this printer,
1677                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1678                  * will keep NT clients happy  --jerry
1679                  */
1680
1681                 if (lp_use_client_driver(snum)
1682                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1683                 {
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685                 }
1686
1687                 /* check smb.conf parameters and the the sec_desc */
1688
1689                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1690                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1691                         ZERO_STRUCTP(r->out.handle);
1692                         return WERR_ACCESS_DENIED;
1693                 }
1694
1695                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1696                                    p->server_info->ptok, snum) ||
1697                     !print_access_check(p->server_info, snum,
1698                                         r->in.access_mask)) {
1699                         DEBUG(3, ("access DENIED for printer open\n"));
1700                         close_printer_handle(p, handle);
1701                         ZERO_STRUCTP(r->out.handle);
1702                         return WERR_ACCESS_DENIED;
1703                 }
1704
1705                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1706                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1707                         close_printer_handle(p, handle);
1708                         ZERO_STRUCTP(r->out.handle);
1709                         return WERR_ACCESS_DENIED;
1710                 }
1711
1712                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1713                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1714                 else
1715                         r->in.access_mask = PRINTER_ACCESS_USE;
1716
1717                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1718                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1719
1720                 break;
1721
1722         default:
1723                 /* sanity check to prevent programmer error */
1724                 ZERO_STRUCTP(r->out.handle);
1725                 return WERR_BADFID;
1726         }
1727
1728         Printer->access_granted = r->in.access_mask;
1729
1730         /*
1731          * If the client sent a devmode in the OpenPrinter() call, then
1732          * save it here in case we get a job submission on this handle
1733          */
1734
1735          if ( (Printer->printer_type != SPLHND_SERVER)
1736                 && r->in.devmode_ctr.devmode )
1737          {
1738                 convert_devicemode_new(Printer->sharename,
1739                                        r->in.devmode_ctr.devmode,
1740                                        &Printer->nt_devmode);
1741          }
1742
1743 #if 0   /* JERRY -- I'm doubtful this is really effective */
1744         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1745            optimization in Windows 2000 clients  --jerry */
1746
1747         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1748                 && (RA_WIN2K == get_remote_arch()) )
1749         {
1750                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1751                 sys_usleep( 500000 );
1752         }
1753 #endif
1754
1755         return WERR_OK;
1756 }
1757
1758 /****************************************************************************
1759 ****************************************************************************/
1760
1761 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1762                                               NT_PRINTER_INFO_LEVEL_2 *d)
1763 {
1764         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1765
1766         if (!r || !d) {
1767                 return false;
1768         }
1769
1770         d->attributes           = r->attributes;
1771         d->priority             = r->priority;
1772         d->default_priority     = r->defaultpriority;
1773         d->starttime            = r->starttime;
1774         d->untiltime            = r->untiltime;
1775         d->status               = r->status;
1776         d->cjobs                = r->cjobs;
1777
1778         fstrcpy(d->servername,  r->servername);
1779         fstrcpy(d->printername, r->printername);
1780         fstrcpy(d->sharename,   r->sharename);
1781         fstrcpy(d->portname,    r->portname);
1782         fstrcpy(d->drivername,  r->drivername);
1783         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1784         fstrcpy(d->location,    r->location);
1785         fstrcpy(d->sepfile,     r->sepfile);
1786         fstrcpy(d->printprocessor, r->printprocessor);
1787         fstrcpy(d->datatype,    r->datatype);
1788         fstrcpy(d->parameters,  r->parameters);
1789
1790         return true;
1791 }
1792
1793 /****************************************************************************
1794 ****************************************************************************/
1795
1796 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1797                                      NT_PRINTER_INFO_LEVEL *printer)
1798 {
1799         bool ret;
1800
1801         switch (info_ctr->level) {
1802         case 2:
1803                 /* allocate memory if needed.  Messy because
1804                    convert_printer_info is used to update an existing
1805                    printer or build a new one */
1806
1807                 if (!printer->info_2) {
1808                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1809                         if (!printer->info_2) {
1810                                 DEBUG(0,("convert_printer_info_new: "
1811                                         "talloc() failed!\n"));
1812                                 return false;
1813                         }
1814                 }
1815
1816                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1817                                                         printer->info_2);
1818                 printer->info_2->setuptime = time(NULL);
1819                 return ret;
1820         }
1821
1822         return false;
1823 }
1824
1825 /*******************************************************************
1826 ********************************************************************/
1827
1828 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1829 {
1830         int i;
1831
1832         if (!sarray) {
1833                 *farray = NULL;
1834                 return true;
1835         }
1836
1837         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1838         if (!*farray) {
1839                 return false;
1840         }
1841
1842         for (i=0; sarray[i] != NULL; i++) {
1843                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1844                 if (!*farray) {
1845                         return false;
1846                 }
1847                 fstrcpy((*farray)[i], sarray[i]);
1848         }
1849
1850         fstrcpy((*farray)[i], "");
1851
1852         return true;
1853 }
1854
1855 /*******************************************************************
1856 ********************************************************************/
1857
1858 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1859                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1860 {
1861         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1862
1863         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1864
1865         if (*p == NULL) {
1866                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1867                 if (*p == NULL) {
1868                         return false;
1869                 }
1870                 ZERO_STRUCTP(*p);
1871         }
1872
1873         d = *p;
1874
1875         d->cversion =                   r->version;
1876
1877         fstrcpy(d->name,                r->driver_name);
1878         fstrcpy(d->environment,         r->architecture);
1879         fstrcpy(d->driverpath,          r->driver_path);
1880         fstrcpy(d->datafile,            r->data_file);
1881         fstrcpy(d->configfile,          r->config_file);
1882         fstrcpy(d->helpfile,            r->help_file);
1883         fstrcpy(d->monitorname,         r->monitor_name);
1884         fstrcpy(d->defaultdatatype,     r->default_datatype);
1885
1886         DEBUGADD(8,( "version:         %d\n", d->cversion));
1887         DEBUGADD(8,( "name:            %s\n", d->name));
1888         DEBUGADD(8,( "environment:     %s\n", d->environment));
1889         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1890         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1891         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1892         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1893         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1894         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1895
1896         if (r->dependent_files) {
1897                 if (!string_array_to_fstring_array(r->dependent_files->string,
1898                                                    &d->dependentfiles)) {
1899                         SAFE_FREE(*p);
1900                         return false;
1901                 }
1902         }
1903
1904         return true;
1905 }
1906
1907 /*******************************************************************
1908 ********************************************************************/
1909
1910 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1911                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1912 {
1913         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1914
1915         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1916
1917         if (*p == NULL) {
1918                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1919                 if (*p == NULL) {
1920                         return false;
1921                 }
1922                 ZERO_STRUCTP(*p);
1923         }
1924
1925         d = *p;
1926
1927         d->version =                    r->version;
1928
1929         fstrcpy(d->name,                r->driver_name);
1930         fstrcpy(d->environment,         r->architecture);
1931         fstrcpy(d->driverpath,          r->driver_path);
1932         fstrcpy(d->datafile,            r->data_file);
1933         fstrcpy(d->configfile,          r->config_file);
1934         fstrcpy(d->helpfile,            r->help_file);
1935         fstrcpy(d->monitorname,         r->monitor_name);
1936         fstrcpy(d->defaultdatatype,     r->default_datatype);
1937
1938         DEBUGADD(8,( "version:         %d\n", d->version));
1939         DEBUGADD(8,( "name:            %s\n", d->name));
1940         DEBUGADD(8,( "environment:     %s\n", d->environment));
1941         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1942         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1943         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1944         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1945         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1946         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1947
1948         if (r->dependent_files) {
1949                 if (!string_array_to_fstring_array(r->dependent_files->string,
1950                                                    &d->dependentfiles)) {
1951                         goto error;
1952                 }
1953         }
1954
1955         if (r->previous_names) {
1956                 if (!string_array_to_fstring_array(r->previous_names->string,
1957                                                    &d->previousnames)) {
1958                         goto error;
1959                 }
1960         }
1961
1962         return true;
1963
1964  error:
1965         SAFE_FREE(*p);
1966         return false;
1967 }
1968
1969 /********************************************************************
1970  ********************************************************************/
1971
1972 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1973                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1974                                         uint32_t level)
1975 {
1976         switch (level) {
1977         case 3:
1978                 printer->info_3 = NULL;
1979                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1980                         return false;
1981                 }
1982                 break;
1983         case 6:
1984                 printer->info_6 = NULL;
1985                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1986                         return false;
1987                 }
1988                 break;
1989         default:
1990                 return false;
1991         }
1992
1993         return true;
1994 }
1995
1996 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1997                                 NT_DEVICEMODE **pp_nt_devmode)
1998 {
1999         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
2000
2001         /*
2002          * Ensure nt_devmode is a valid pointer
2003          * as we will be overwriting it.
2004          */
2005
2006         if (nt_devmode == NULL) {
2007                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2008                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2009                         return False;
2010         }
2011
2012         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2013         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2014
2015         nt_devmode->specversion=devmode->specversion;
2016         nt_devmode->driverversion=devmode->driverversion;
2017         nt_devmode->size=devmode->size;
2018         nt_devmode->fields=devmode->fields;
2019         nt_devmode->orientation=devmode->orientation;
2020         nt_devmode->papersize=devmode->papersize;
2021         nt_devmode->paperlength=devmode->paperlength;
2022         nt_devmode->paperwidth=devmode->paperwidth;
2023         nt_devmode->scale=devmode->scale;
2024         nt_devmode->copies=devmode->copies;
2025         nt_devmode->defaultsource=devmode->defaultsource;
2026         nt_devmode->printquality=devmode->printquality;
2027         nt_devmode->color=devmode->color;
2028         nt_devmode->duplex=devmode->duplex;
2029         nt_devmode->yresolution=devmode->yresolution;
2030         nt_devmode->ttoption=devmode->ttoption;
2031         nt_devmode->collate=devmode->collate;
2032
2033         nt_devmode->logpixels=devmode->logpixels;
2034         nt_devmode->bitsperpel=devmode->bitsperpel;
2035         nt_devmode->pelswidth=devmode->pelswidth;
2036         nt_devmode->pelsheight=devmode->pelsheight;
2037         nt_devmode->displayflags=devmode->displayflags;
2038         nt_devmode->displayfrequency=devmode->displayfrequency;
2039         nt_devmode->icmmethod=devmode->icmmethod;
2040         nt_devmode->icmintent=devmode->icmintent;
2041         nt_devmode->mediatype=devmode->mediatype;
2042         nt_devmode->dithertype=devmode->dithertype;
2043         nt_devmode->reserved1=devmode->reserved1;
2044         nt_devmode->reserved2=devmode->reserved2;
2045         nt_devmode->panningwidth=devmode->panningwidth;
2046         nt_devmode->panningheight=devmode->panningheight;
2047
2048         /*
2049          * Only change private and driverextra if the incoming devmode
2050          * has a new one. JRA.
2051          */
2052
2053         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2054                 SAFE_FREE(nt_devmode->nt_dev_private);
2055                 nt_devmode->driverextra=devmode->driverextra;
2056                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2057                         return False;
2058                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2059         }
2060
2061         *pp_nt_devmode = nt_devmode;
2062
2063         return True;
2064 }
2065
2066 /********************************************************************
2067  * _spoolss_enddocprinter_internal.
2068  ********************************************************************/
2069
2070 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2071 {
2072         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2073         int snum;
2074
2075         if (!Printer) {
2076                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2077                 return WERR_BADFID;
2078         }
2079
2080         if (!get_printer_snum(p, handle, &snum, NULL))
2081                 return WERR_BADFID;
2082
2083         Printer->document_started=False;
2084         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2085         /* error codes unhandled so far ... */
2086
2087         return WERR_OK;
2088 }
2089
2090 /****************************************************************
2091  _spoolss_ClosePrinter
2092 ****************************************************************/
2093
2094 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2095                              struct spoolss_ClosePrinter *r)
2096 {
2097         POLICY_HND *handle = r->in.handle;
2098
2099         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2100
2101         if (Printer && Printer->document_started)
2102                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2103
2104         if (!close_printer_handle(p, handle))
2105                 return WERR_BADFID;
2106
2107         /* clear the returned printer handle.  Observed behavior
2108            from Win2k server.  Don't think this really matters.
2109            Previous code just copied the value of the closed
2110            handle.    --jerry */
2111
2112         ZERO_STRUCTP(r->out.handle);
2113
2114         return WERR_OK;
2115 }
2116
2117 /****************************************************************
2118  _spoolss_DeletePrinter
2119 ****************************************************************/
2120
2121 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2122                               struct spoolss_DeletePrinter *r)
2123 {
2124         POLICY_HND *handle = r->in.handle;
2125         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2126         WERROR result;
2127
2128         if (Printer && Printer->document_started)
2129                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2130
2131         result = delete_printer_handle(p, handle);
2132
2133         update_c_setprinter(False);
2134
2135         return result;
2136 }
2137
2138 /*******************************************************************
2139  * static function to lookup the version id corresponding to an
2140  * long architecture string
2141  ******************************************************************/
2142
2143 static int get_version_id (char * arch)
2144 {
2145         int i;
2146         struct table_node archi_table[]= {
2147
2148                 {"Windows 4.0",          "WIN40",       0 },
2149                 {"Windows NT x86",       "W32X86",      2 },
2150                 {"Windows NT R4000",     "W32MIPS",     2 },
2151                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2152                 {"Windows NT PowerPC",   "W32PPC",      2 },
2153                 {"Windows IA64",         "IA64",        3 },
2154                 {"Windows x64",          "x64",         3 },
2155                 {NULL,                   "",            -1 }
2156         };
2157
2158         for (i=0; archi_table[i].long_archi != NULL; i++)
2159         {
2160                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2161                         return (archi_table[i].version);
2162         }
2163
2164         return -1;
2165 }
2166
2167 /****************************************************************
2168  _spoolss_DeletePrinterDriver
2169 ****************************************************************/
2170
2171 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2172                                     struct spoolss_DeletePrinterDriver *r)
2173 {
2174         char *driver;
2175         char *arch;
2176         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2177         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2178         int                             version;
2179         WERROR                          status;
2180         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2181         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2182
2183         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184            and not a printer admin, then fail */
2185
2186         if ( (p->server_info->utok.uid != 0)
2187                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2188                 && !token_contains_name_in_list(
2189                         uidtoname(p->server_info->utok.uid), NULL,
2190                         NULL, p->server_info->ptok,
2191                         lp_printer_admin(-1)) )
2192         {
2193                 return WERR_ACCESS_DENIED;
2194         }
2195
2196         driver = CONST_DISCARD(char *, r->in.driver);
2197         arch   = CONST_DISCARD(char *, r->in.architecture);
2198
2199         /* check that we have a valid driver name first */
2200
2201         if ((version=get_version_id(arch)) == -1)
2202                 return WERR_INVALID_ENVIRONMENT;
2203
2204         ZERO_STRUCT(info);
2205         ZERO_STRUCT(info_win2k);
2206
2207         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2208         {
2209                 /* try for Win2k driver if "Windows NT x86" */
2210
2211                 if ( version == 2 ) {
2212                         version = 3;
2213                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2214                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2215                                 goto done;
2216                         }
2217                 }
2218                 /* otherwise it was a failure */
2219                 else {
2220                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2221                         goto done;
2222                 }
2223
2224         }
2225
2226         if (printer_driver_in_use(info.info_3)) {
2227                 status = WERR_PRINTER_DRIVER_IN_USE;
2228                 goto done;
2229         }
2230
2231         if ( version == 2 )
2232         {
2233                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2234                 {
2235                         /* if we get to here, we now have 2 driver info structures to remove */
2236                         /* remove the Win2k driver first*/
2237
2238                         status_win2k = delete_printer_driver(
2239                                 p, info_win2k.info_3, 3, False );
2240                         free_a_printer_driver( info_win2k, 3 );
2241
2242                         /* this should not have failed---if it did, report to client */
2243                         if ( !W_ERROR_IS_OK(status_win2k) )
2244                         {
2245                                 status = status_win2k;
2246                                 goto done;
2247                         }
2248                 }
2249         }
2250
2251         status = delete_printer_driver(p, info.info_3, version, False);
2252
2253         /* if at least one of the deletes succeeded return OK */
2254
2255         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2256                 status = WERR_OK;
2257
2258 done:
2259         free_a_printer_driver( info, 3 );
2260
2261         return status;
2262 }
2263
2264 /****************************************************************
2265  _spoolss_DeletePrinterDriverEx
2266 ****************************************************************/
2267
2268 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2269                                       struct spoolss_DeletePrinterDriverEx *r)
2270 {
2271         char *driver;
2272         char *arch;
2273         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2274         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2275         int                             version;
2276         uint32_t                        flags = r->in.delete_flags;
2277         bool                            delete_files;
2278         WERROR                          status;
2279         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2280         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2281
2282         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2283            and not a printer admin, then fail */
2284
2285         if ( (p->server_info->utok.uid != 0)
2286                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2287                 && !token_contains_name_in_list(
2288                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2289                         p->server_info->ptok, lp_printer_admin(-1)) )
2290         {
2291                 return WERR_ACCESS_DENIED;
2292         }
2293
2294         driver = CONST_DISCARD(char *, r->in.driver);
2295         arch   = CONST_DISCARD(char *, r->in.architecture);
2296
2297         /* check that we have a valid driver name first */
2298         if ((version=get_version_id(arch)) == -1) {
2299                 /* this is what NT returns */
2300                 return WERR_INVALID_ENVIRONMENT;
2301         }
2302
2303         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2304                 version = r->in.version;
2305
2306         ZERO_STRUCT(info);
2307         ZERO_STRUCT(info_win2k);
2308
2309         status = get_a_printer_driver(&info, 3, driver, arch, version);
2310
2311         if ( !W_ERROR_IS_OK(status) )
2312         {
2313                 /*
2314                  * if the client asked for a specific version,
2315                  * or this is something other than Windows NT x86,
2316                  * then we've failed
2317                  */
2318
2319                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2320                         goto done;
2321
2322                 /* try for Win2k driver if "Windows NT x86" */
2323
2324                 version = 3;
2325                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2326                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2327                         goto done;
2328                 }
2329         }
2330
2331         if ( printer_driver_in_use(info.info_3) ) {
2332                 status = WERR_PRINTER_DRIVER_IN_USE;
2333                 goto done;
2334         }
2335
2336         /*
2337          * we have a couple of cases to consider.
2338          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2339          *     then the delete should fail if **any** files overlap with
2340          *     other drivers
2341          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2342          *     non-overlapping files
2343          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2344          *     is set, the do not delete any files
2345          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2346          */
2347
2348         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2349
2350         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2351
2352         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2353                 /* no idea of the correct error here */
2354                 status = WERR_ACCESS_DENIED;
2355                 goto done;
2356         }
2357
2358
2359         /* also check for W32X86/3 if necessary; maybe we already have? */
2360
2361         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2362                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2363                 {
2364
2365                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2366                                 /* no idea of the correct error here */
2367                                 free_a_printer_driver( info_win2k, 3 );
2368                                 status = WERR_ACCESS_DENIED;
2369                                 goto done;
2370                         }
2371
2372                         /* if we get to here, we now have 2 driver info structures to remove */
2373                         /* remove the Win2k driver first*/
2374
2375                         status_win2k = delete_printer_driver(
2376                                 p, info_win2k.info_3, 3, delete_files);
2377                         free_a_printer_driver( info_win2k, 3 );
2378
2379                         /* this should not have failed---if it did, report to client */
2380
2381                         if ( !W_ERROR_IS_OK(status_win2k) )
2382                                 goto done;
2383                 }
2384         }
2385
2386         status = delete_printer_driver(p, info.info_3, version, delete_files);
2387
2388         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2389                 status = WERR_OK;
2390 done:
2391         free_a_printer_driver( info, 3 );
2392
2393         return status;
2394 }
2395
2396
2397 /****************************************************************************
2398  Internal routine for retreiving printerdata
2399  ***************************************************************************/
2400
2401 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2402                                   const char *key, const char *value, uint32 *type, uint8 **data,
2403                                   uint32 *needed, uint32 in_size  )
2404 {
2405         REGISTRY_VALUE          *val;
2406         uint32                  size;
2407         int                     data_len;
2408
2409         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2410                 return WERR_BADFILE;
2411
2412         *type = regval_type( val );
2413
2414         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2415
2416         size = regval_size( val );
2417
2418         /* copy the min(in_size, len) */
2419
2420         if ( in_size ) {
2421                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2422
2423                 /* special case for 0 length values */
2424                 if ( data_len ) {
2425                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2426                                 return WERR_NOMEM;
2427                 }
2428                 else {
2429                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2430                                 return WERR_NOMEM;
2431                 }
2432         }
2433         else
2434                 *data = NULL;
2435
2436         *needed = size;
2437
2438         DEBUG(5,("get_printer_dataex: copy done\n"));
2439
2440         return WERR_OK;
2441 }
2442
2443 /****************************************************************************
2444  Internal routine for removing printerdata
2445  ***************************************************************************/
2446
2447 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2448 {
2449         return delete_printer_data( printer->info_2, key, value );
2450 }
2451
2452 /****************************************************************************
2453  Internal routine for storing printerdata
2454  ***************************************************************************/
2455
2456 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2457                                   uint32 type, uint8 *data, int real_len  )
2458 {
2459         /* the registry objects enforce uniqueness based on value name */
2460
2461         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2462 }
2463
2464 /********************************************************************
2465  GetPrinterData on a printer server Handle.
2466 ********************************************************************/
2467
2468 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2469 {
2470         int i;
2471
2472         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2473
2474         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2475                 *type = REG_DWORD;
2476                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2477                         return WERR_NOMEM;
2478                 SIVAL(*data, 0, 0x00);
2479                 *needed = 0x4;
2480                 return WERR_OK;
2481         }
2482
2483         if (!StrCaseCmp(value, "BeepEnabled")) {
2484                 *type = REG_DWORD;
2485                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2486                         return WERR_NOMEM;
2487                 SIVAL(*data, 0, 0x00);
2488                 *needed = 0x4;
2489                 return WERR_OK;
2490         }
2491
2492         if (!StrCaseCmp(value, "EventLog")) {
2493                 *type = REG_DWORD;
2494                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2495                         return WERR_NOMEM;
2496                 /* formally was 0x1b */
2497                 SIVAL(*data, 0, 0x0);
2498                 *needed = 0x4;
2499                 return WERR_OK;
2500         }
2501
2502         if (!StrCaseCmp(value, "NetPopup")) {
2503                 *type = REG_DWORD;
2504                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2505                         return WERR_NOMEM;
2506                 SIVAL(*data, 0, 0x00);
2507                 *needed = 0x4;
2508                 return WERR_OK;
2509         }
2510
2511         if (!StrCaseCmp(value, "MajorVersion")) {
2512                 *type = REG_DWORD;
2513                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2514                         return WERR_NOMEM;
2515
2516                 /* Windows NT 4.0 seems to not allow uploading of drivers
2517                    to a server that reports 0x3 as the MajorVersion.
2518                    need to investigate more how Win2k gets around this .
2519                    -- jerry */
2520
2521                 if ( RA_WINNT == get_remote_arch() )
2522                         SIVAL(*data, 0, 2);
2523                 else
2524                         SIVAL(*data, 0, 3);
2525
2526                 *needed = 0x4;
2527                 return WERR_OK;
2528         }
2529
2530         if (!StrCaseCmp(value, "MinorVersion")) {
2531                 *type = REG_DWORD;
2532                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2533                         return WERR_NOMEM;
2534                 SIVAL(*data, 0, 0);
2535                 *needed = 0x4;
2536                 return WERR_OK;
2537         }
2538
2539         /* REG_BINARY
2540          *  uint32 size          = 0x114
2541          *  uint32 major         = 5
2542          *  uint32 minor         = [0|1]
2543          *  uint32 build         = [2195|2600]
2544          *  extra unicode string = e.g. "Service Pack 3"
2545          */
2546         if (!StrCaseCmp(value, "OSVersion")) {
2547                 *type = REG_BINARY;
2548                 *needed = 0x114;
2549
2550                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2551                         return WERR_NOMEM;
2552
2553                 SIVAL(*data, 0, *needed);       /* size */
2554                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2555                 SIVAL(*data, 8, 0);
2556                 SIVAL(*data, 12, 2195);         /* build */
2557
2558                 /* leave extra string empty */
2559
2560                 return WERR_OK;
2561         }
2562
2563
2564         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2565                 const char *string="C:\\PRINTERS";
2566                 *type = REG_SZ;
2567                 *needed = 2*(strlen(string)+1);
2568                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2569                         return WERR_NOMEM;
2570                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2571
2572                 /* it's done by hand ready to go on the wire */
2573                 for (i=0; i<strlen(string); i++) {
2574                         (*data)[2*i]=string[i];
2575                         (*data)[2*i+1]='\0';
2576                 }
2577                 return WERR_OK;
2578         }
2579
2580         if (!StrCaseCmp(value, "Architecture")) {
2581                 const char *string="Windows NT x86";
2582                 *type = REG_SZ;
2583                 *needed = 2*(strlen(string)+1);
2584                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2585                         return WERR_NOMEM;
2586                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2587                 for (i=0; i<strlen(string); i++) {
2588                         (*data)[2*i]=string[i];
2589                         (*data)[2*i+1]='\0';
2590                 }
2591                 return WERR_OK;
2592         }
2593
2594         if (!StrCaseCmp(value, "DsPresent")) {
2595                 *type = REG_DWORD;
2596                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2597                         return WERR_NOMEM;
2598
2599                 /* only show the publish check box if we are a
2600                    memeber of a AD domain */
2601
2602                 if ( lp_security() == SEC_ADS )
2603                         SIVAL(*data, 0, 0x01);
2604                 else
2605                         SIVAL(*data, 0, 0x00);
2606
2607                 *needed = 0x4;
2608                 return WERR_OK;
2609         }
2610
2611         if (!StrCaseCmp(value, "DNSMachineName")) {
2612                 const char *hostname = get_mydnsfullname();
2613
2614                 if (!hostname)
2615                         return WERR_BADFILE;
2616                 *type = REG_SZ;
2617                 *needed = 2*(strlen(hostname)+1);
2618                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2619                         return WERR_NOMEM;
2620                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2621                 for (i=0; i<strlen(hostname); i++) {
2622                         (*data)[2*i]=hostname[i];
2623                         (*data)[2*i+1]='\0';
2624                 }
2625                 return WERR_OK;
2626         }
2627
2628
2629         return WERR_BADFILE;
2630 }
2631
2632 /********************************************************************
2633  * spoolss_getprinterdata
2634  ********************************************************************/
2635
2636 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2637 {
2638         POLICY_HND      *handle = &q_u->handle;
2639         UNISTR2         *valuename = &q_u->valuename;
2640         uint32          in_size = q_u->size;
2641         uint32          *type = &r_u->type;
2642         uint32          *out_size = &r_u->size;
2643         uint8           **data = &r_u->data;
2644         uint32          *needed = &r_u->needed;
2645         WERROR          status;
2646         fstring         value;
2647         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2648         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2649         int             snum = 0;
2650
2651         /*
2652          * Reminder: when it's a string, the length is in BYTES
2653          * even if UNICODE is negociated.
2654          *
2655          * JFM, 4/19/1999
2656          */
2657
2658         *out_size = in_size;
2659
2660         /* in case of problem, return some default values */
2661
2662         *needed = 0;
2663         *type   = 0;
2664
2665         DEBUG(4,("_spoolss_getprinterdata\n"));
2666
2667         if ( !Printer ) {
2668                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2669                 status = WERR_BADFID;
2670                 goto done;
2671         }
2672
2673         unistr2_to_ascii(value, valuename, sizeof(value));
2674
2675         if ( Printer->printer_type == SPLHND_SERVER )
2676                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2677         else
2678         {
2679                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2680                         status = WERR_BADFID;
2681                         goto done;
2682                 }
2683
2684                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2685                 if ( !W_ERROR_IS_OK(status) )
2686                         goto done;
2687
2688                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2689
2690                 if ( strequal(value, "ChangeId") ) {
2691                         *type = REG_DWORD;
2692                         *needed = sizeof(uint32);
2693                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2694                                 status = WERR_NOMEM;
2695                                 goto done;
2696                         }
2697                         SIVAL( *data, 0, printer->info_2->changeid );
2698                         status = WERR_OK;
2699                 }
2700                 else
2701                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2702         }
2703
2704         if (*needed > *out_size)
2705                 status = WERR_MORE_DATA;
2706
2707 done:
2708         if ( !W_ERROR_IS_OK(status) )
2709         {
2710                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2711
2712                 /* reply this param doesn't exist */
2713
2714                 if ( *out_size ) {
2715                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2716                                 if ( printer )
2717                                         free_a_printer( &printer, 2 );
2718                                 return WERR_NOMEM;
2719                         }
2720                 } else {
2721                         *data = NULL;
2722                 }
2723         }
2724
2725         /* cleanup & exit */
2726
2727         if ( printer )
2728                 free_a_printer( &printer, 2 );
2729
2730         return status;
2731 }
2732
2733 /*********************************************************
2734  Connect to the client machine.
2735 **********************************************************/
2736
2737 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2738                         struct sockaddr_storage *client_ss, const char *remote_machine)
2739 {
2740         NTSTATUS ret;
2741         struct cli_state *the_cli;
2742         struct sockaddr_storage rm_addr;
2743
2744         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2745                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2746                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2747                         return False;
2748                 }
2749
2750                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2751                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2752                         return False;
2753                 }
2754         } else {
2755                 char addr[INET6_ADDRSTRLEN];
2756                 rm_addr = *client_ss;
2757                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2758                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2759                         addr));
2760         }
2761
2762         /* setup the connection */
2763
2764         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2765                 &rm_addr, 0, "IPC$", "IPC",
2766                 "", /* username */
2767                 "", /* domain */
2768                 "", /* password */
2769                 0, lp_client_signing(), NULL );
2770
2771         if ( !NT_STATUS_IS_OK( ret ) ) {
2772                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2773                         remote_machine ));
2774                 return False;
2775         }
2776
2777         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2778                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2779                 cli_shutdown(the_cli);
2780                 return False;
2781         }
2782
2783         /*
2784          * Ok - we have an anonymous connection to the IPC$ share.
2785          * Now start the NT Domain stuff :-).
2786          */
2787
2788         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2789         if (!NT_STATUS_IS_OK(ret)) {
2790                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2791                         remote_machine, nt_errstr(ret)));
2792                 cli_shutdown(the_cli);
2793                 return False;
2794         }
2795
2796         return True;
2797 }
2798
2799 /***************************************************************************
2800  Connect to the client.
2801 ****************************************************************************/
2802
2803 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2804                                         uint32 localprinter, uint32 type,
2805                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2806 {
2807         WERROR result;
2808         NTSTATUS status;
2809
2810         /*
2811          * If it's the first connection, contact the client
2812          * and connect to the IPC$ share anonymously
2813          */
2814         if (smb_connections==0) {
2815                 fstring unix_printer;
2816
2817                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2818
2819                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2820                         return False;
2821
2822                 messaging_register(smbd_messaging_context(), NULL,
2823                                    MSG_PRINTER_NOTIFY2,
2824                                    receive_notify2_message_list);
2825                 /* Tell the connections db we're now interested in printer
2826                  * notify messages. */
2827                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2828         }
2829
2830         /*
2831          * Tell the specific printing tdb we want messages for this printer
2832          * by registering our PID.
2833          */
2834
2835         if (!print_notify_register_pid(snum))
2836                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2837
2838         smb_connections++;
2839
2840         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2841                                                  printer,
2842                                                  localprinter,
2843                                                  type,
2844                                                  0,
2845                                                  NULL,
2846                                                  handle,
2847                                                  &result);
2848         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2849                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2850                         win_errstr(result)));
2851
2852         return (W_ERROR_IS_OK(result));
2853 }
2854
2855 /****************************************************************
2856  ****************************************************************/
2857
2858 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2859                                                              const struct spoolss_NotifyOption *r)
2860 {
2861         struct spoolss_NotifyOption *option;
2862         uint32_t i,k;
2863
2864         if (!r) {
2865                 return NULL;
2866         }
2867
2868         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2869         if (!option) {
2870                 return NULL;
2871         }
2872
2873         *option = *r;
2874
2875         if (!option->count) {
2876                 return option;
2877         }
2878
2879         option->types = talloc_zero_array(option,
2880                 struct spoolss_NotifyOptionType, option->count);
2881         if (!option->types) {
2882                 talloc_free(option);
2883                 return NULL;
2884         }
2885
2886         for (i=0; i < option->count; i++) {
2887                 option->types[i] = r->types[i];
2888
2889                 if (option->types[i].count) {
2890                         option->types[i].fields = talloc_zero_array(option,
2891                                 enum spoolss_Field, option->types[i].count);
2892                         if (!option->types[i].fields) {
2893                                 talloc_free(option);
2894                                 return NULL;
2895                         }
2896                         for (k=0; k<option->types[i].count; k++) {
2897                                 option->types[i].fields[k] =
2898                                         r->types[i].fields[k];
2899                         }
2900                 }
2901         }
2902
2903         return option;
2904 }
2905
2906 /****************************************************************
2907  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2908  *
2909  * before replying OK: status=0 a rpc call is made to the workstation
2910  * asking ReplyOpenPrinter
2911  *
2912  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2913  * called from api_spoolss_rffpcnex
2914 ****************************************************************/
2915
2916 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2917                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2918 {
2919         POLICY_HND *handle = r->in.handle;
2920         int snum = -1;
2921         struct spoolss_NotifyOption *option = r->in.notify_options;
2922         struct sockaddr_storage client_ss;
2923
2924         /* store the notify value in the printer struct */
2925
2926         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2927
2928         if (!Printer) {
2929                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2930                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2931                 return WERR_BADFID;
2932         }
2933
2934         Printer->notify.flags           = r->in.flags;
2935         Printer->notify.options         = r->in.options;
2936         Printer->notify.printerlocal    = r->in.printer_local;
2937
2938         TALLOC_FREE(Printer->notify.option);
2939         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2940
2941         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2942
2943         /* Connect to the client machine and send a ReplyOpenPrinter */
2944
2945         if ( Printer->printer_type == SPLHND_SERVER)
2946                 snum = -1;
2947         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2948                         !get_printer_snum(p, handle, &snum, NULL) )
2949                 return WERR_BADFID;
2950
2951         if (!interpret_string_addr(&client_ss, p->client_address,
2952                                    AI_NUMERICHOST)) {
2953                 return WERR_SERVER_UNAVAILABLE;
2954         }
2955
2956         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2957                                         Printer->notify.printerlocal, 1,
2958                                         &Printer->notify.client_hnd, &client_ss))
2959                 return WERR_SERVER_UNAVAILABLE;
2960
2961         Printer->notify.client_connected=True;
2962
2963         return WERR_OK;
2964 }
2965
2966 /*******************************************************************
2967  * fill a notify_info_data with the servername
2968  ********************************************************************/
2969
2970 void spoolss_notify_server_name(int snum,
2971                                        struct spoolss_Notify *data,
2972                                        print_queue_struct *queue,
2973                                        NT_PRINTER_INFO_LEVEL *printer,
2974                                        TALLOC_CTX *mem_ctx)
2975 {
2976         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2977 }
2978
2979 /*******************************************************************
2980  * fill a notify_info_data with the printername (not including the servername).
2981  ********************************************************************/
2982
2983 void spoolss_notify_printer_name(int snum,
2984                                         struct spoolss_Notify *data,
2985                                         print_queue_struct *queue,
2986                                         NT_PRINTER_INFO_LEVEL *printer,
2987                                         TALLOC_CTX *mem_ctx)
2988 {
2989         /* the notify name should not contain the \\server\ part */
2990         char *p = strrchr(printer->info_2->printername, '\\');
2991
2992         if (!p) {
2993                 p = printer->info_2->printername;
2994         } else {
2995                 p++;
2996         }
2997
2998         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with the servicename
3003  ********************************************************************/
3004
3005 void spoolss_notify_share_name(int snum,
3006                                       struct spoolss_Notify *data,
3007                                       print_queue_struct *queue,
3008                                       NT_PRINTER_INFO_LEVEL *printer,
3009                                       TALLOC_CTX *mem_ctx)
3010 {
3011         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3012 }
3013
3014 /*******************************************************************
3015  * fill a notify_info_data with the port name
3016  ********************************************************************/
3017
3018 void spoolss_notify_port_name(int snum,
3019                                      struct spoolss_Notify *data,
3020                                      print_queue_struct *queue,
3021                                      NT_PRINTER_INFO_LEVEL *printer,
3022                                      TALLOC_CTX *mem_ctx)
3023 {
3024         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3025 }
3026
3027 /*******************************************************************
3028  * fill a notify_info_data with the printername
3029  * but it doesn't exist, have to see what to do
3030  ********************************************************************/
3031
3032 void spoolss_notify_driver_name(int snum,
3033                                        struct spoolss_Notify *data,
3034                                        print_queue_struct *queue,
3035                                        NT_PRINTER_INFO_LEVEL *printer,
3036                                        TALLOC_CTX *mem_ctx)
3037 {
3038         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3039 }
3040
3041 /*******************************************************************
3042  * fill a notify_info_data with the comment
3043  ********************************************************************/
3044
3045 void spoolss_notify_comment(int snum,
3046                                    struct spoolss_Notify *data,
3047                                    print_queue_struct *queue,
3048                                    NT_PRINTER_INFO_LEVEL *printer,
3049                                    TALLOC_CTX *mem_ctx)
3050 {
3051         char *p;
3052
3053         if (*printer->info_2->comment == '\0') {
3054                 p = lp_comment(snum);
3055         } else {
3056                 p = printer->info_2->comment;
3057         }
3058
3059         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with the comment
3064  * location = "Room 1, floor 2, building 3"
3065  ********************************************************************/
3066
3067 void spoolss_notify_location(int snum,
3068                                     struct spoolss_Notify *data,
3069                                     print_queue_struct *queue,
3070                                     NT_PRINTER_INFO_LEVEL *printer,
3071                                     TALLOC_CTX *mem_ctx)
3072 {
3073         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3074 }
3075
3076 /*******************************************************************
3077  * fill a notify_info_data with the device mode
3078  * jfm:xxxx don't to it for know but that's a real problem !!!
3079  ********************************************************************/
3080
3081 static void spoolss_notify_devmode(int snum,
3082                                    struct spoolss_Notify *data,
3083                                    print_queue_struct *queue,
3084                                    NT_PRINTER_INFO_LEVEL *printer,
3085                                    TALLOC_CTX *mem_ctx)
3086 {
3087         /* for a dummy implementation we have to zero the fields */
3088         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with the separator file name
3093  ********************************************************************/
3094
3095 void spoolss_notify_sepfile(int snum,
3096                                    struct spoolss_Notify *data,
3097                                    print_queue_struct *queue,
3098                                    NT_PRINTER_INFO_LEVEL *printer,
3099                                    TALLOC_CTX *mem_ctx)
3100 {
3101         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with the print processor
3106  * jfm:xxxx return always winprint to indicate we don't do anything to it
3107  ********************************************************************/
3108
3109 void spoolss_notify_print_processor(int snum,
3110                                            struct spoolss_Notify *data,
3111                                            print_queue_struct *queue,
3112                                            NT_PRINTER_INFO_LEVEL *printer,
3113                                            TALLOC_CTX *mem_ctx)
3114 {
3115         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3116 }
3117
3118 /*******************************************************************
3119  * fill a notify_info_data with the print processor options
3120  * jfm:xxxx send an empty string
3121  ********************************************************************/
3122
3123 void spoolss_notify_parameters(int snum,
3124                                       struct spoolss_Notify *data,
3125                                       print_queue_struct *queue,
3126                                       NT_PRINTER_INFO_LEVEL *printer,
3127                                       TALLOC_CTX *mem_ctx)
3128 {
3129         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with the data type
3134  * jfm:xxxx always send RAW as data type
3135  ********************************************************************/
3136
3137 void spoolss_notify_datatype(int snum,
3138                                     struct spoolss_Notify *data,
3139                                     print_queue_struct *queue,
3140                                     NT_PRINTER_INFO_LEVEL *printer,
3141                                     TALLOC_CTX *mem_ctx)
3142 {
3143         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3144 }
3145
3146 /*******************************************************************
3147  * fill a notify_info_data with the security descriptor
3148  * jfm:xxxx send an null pointer to say no security desc
3149  * have to implement security before !
3150  ********************************************************************/
3151
3152 static void spoolss_notify_security_desc(int snum,
3153                                          struct spoolss_Notify *data,
3154                                          print_queue_struct *queue,
3155                                          NT_PRINTER_INFO_LEVEL *printer,
3156                                          TALLOC_CTX *mem_ctx)
3157 {
3158         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3159                                           printer->info_2->secdesc_buf->sd_size,
3160                                           printer->info_2->secdesc_buf->sd);
3161 }
3162
3163 /*******************************************************************
3164  * fill a notify_info_data with the attributes
3165  * jfm:xxxx a samba printer is always shared
3166  ********************************************************************/
3167
3168 void spoolss_notify_attributes(int snum,
3169                                       struct spoolss_Notify *data,
3170                                       print_queue_struct *queue,
3171                                       NT_PRINTER_INFO_LEVEL *printer,
3172                                       TALLOC_CTX *mem_ctx)
3173 {
3174         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3175 }
3176
3177 /*******************************************************************
3178  * fill a notify_info_data with the priority
3179  ********************************************************************/
3180
3181 static void spoolss_notify_priority(int snum,
3182                                     struct spoolss_Notify *data,
3183                                     print_queue_struct *queue,
3184                                     NT_PRINTER_INFO_LEVEL *printer,
3185                                     TALLOC_CTX *mem_ctx)
3186 {
3187         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with the default priority
3192  ********************************************************************/
3193
3194 static void spoolss_notify_default_priority(int snum,
3195                                             struct spoolss_Notify *data,
3196                                             print_queue_struct *queue,
3197                                             NT_PRINTER_INFO_LEVEL *printer,
3198                                             TALLOC_CTX *mem_ctx)
3199 {
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3201 }
3202
3203 /*******************************************************************
3204  * fill a notify_info_data with the start time
3205  ********************************************************************/
3206
3207 static void spoolss_notify_start_time(int snum,
3208                                       struct spoolss_Notify *data,
3209                                       print_queue_struct *queue,
3210                                       NT_PRINTER_INFO_LEVEL *printer,
3211                                       TALLOC_CTX *mem_ctx)
3212 {
3213         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3214 }
3215
3216 /*******************************************************************
3217  * fill a notify_info_data with the until time
3218  ********************************************************************/
3219
3220 static void spoolss_notify_until_time(int snum,
3221                                       struct spoolss_Notify *data,
3222                                       print_queue_struct *queue,
3223                                       NT_PRINTER_INFO_LEVEL *printer,
3224                                       TALLOC_CTX *mem_ctx)
3225 {
3226         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3227 }
3228
3229 /*******************************************************************
3230  * fill a notify_info_data with the status
3231  ********************************************************************/
3232
3233 static void spoolss_notify_status(int snum,
3234                                   struct spoolss_Notify *data,
3235                                   print_queue_struct *queue,
3236                                   NT_PRINTER_INFO_LEVEL *printer,
3237                                   TALLOC_CTX *mem_ctx)
3238 {
3239         print_status_struct status;
3240
3241         print_queue_length(snum, &status);
3242         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3243 }
3244
3245 /*******************************************************************
3246  * fill a notify_info_data with the number of jobs queued
3247  ********************************************************************/
3248
3249 void spoolss_notify_cjobs(int snum,
3250                                  struct spoolss_Notify *data,
3251                                  print_queue_struct *queue,
3252                                  NT_PRINTER_INFO_LEVEL *printer,
3253                                  TALLOC_CTX *mem_ctx)
3254 {
3255         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3256 }
3257
3258 /*******************************************************************
3259  * fill a notify_info_data with the average ppm
3260  ********************************************************************/
3261
3262 static void spoolss_notify_average_ppm(int snum,
3263                                        struct spoolss_Notify *data,
3264                                        print_queue_struct *queue,
3265                                        NT_PRINTER_INFO_LEVEL *printer,
3266                                        TALLOC_CTX *mem_ctx)
3267 {
3268         /* always respond 8 pages per minutes */
3269         /* a little hard ! */
3270         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3271 }
3272
3273 /*******************************************************************
3274  * fill a notify_info_data with username
3275  ********************************************************************/
3276
3277 static void spoolss_notify_username(int snum,
3278                                     struct spoolss_Notify *data,
3279                                     print_queue_struct *queue,
3280                                     NT_PRINTER_INFO_LEVEL *printer,
3281                                     TALLOC_CTX *mem_ctx)
3282 {
3283         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3284 }
3285
3286 /*******************************************************************
3287  * fill a notify_info_data with job status
3288  ********************************************************************/
3289
3290 static void spoolss_notify_job_status(int snum,
3291                                       struct spoolss_Notify *data,
3292                                       print_queue_struct *queue,
3293                                       NT_PRINTER_INFO_LEVEL *printer,
3294                                       TALLOC_CTX *mem_ctx)
3295 {
3296         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3297 }
3298
3299 /*******************************************************************
3300  * fill a notify_info_data with job name
3301  ********************************************************************/
3302
3303 static void spoolss_notify_job_name(int snum,
3304                                     struct spoolss_Notify *data,
3305                                     print_queue_struct *queue,
3306                                     NT_PRINTER_INFO_LEVEL *printer,
3307                                     TALLOC_CTX *mem_ctx)
3308 {
3309         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3310 }
3311
3312 /*******************************************************************
3313  * fill a notify_info_data with job status
3314  ********************************************************************/
3315
3316 static void spoolss_notify_job_status_string(int snum,
3317                                              struct spoolss_Notify *data,
3318                                              print_queue_struct *queue,
3319                                              NT_PRINTER_INFO_LEVEL *printer,
3320                                              TALLOC_CTX *mem_ctx)
3321 {
3322         /*
3323          * Now we're returning job status codes we just return a "" here. JRA.
3324          */
3325
3326         const char *p = "";
3327
3328 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3329         p = "unknown";
3330
3331         switch (queue->status) {
3332         case LPQ_QUEUED:
3333                 p = "Queued";
3334                 break;
3335         case LPQ_PAUSED:
3336                 p = "";    /* NT provides the paused string */
3337                 break;
3338         case LPQ_SPOOLING:
3339                 p = "Spooling";
3340                 break;
3341         case LPQ_PRINTING:
3342                 p = "Printing";
3343                 break;
3344         }
3345 #endif /* NO LONGER NEEDED. */
3346
3347         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3348 }
3349
3350 /*******************************************************************
3351  * fill a notify_info_data with job time
3352  ********************************************************************/
3353
3354 static void spoolss_notify_job_time(int snum,
3355                                     struct spoolss_Notify *data,
3356                                     print_queue_struct *queue,
3357                                     NT_PRINTER_INFO_LEVEL *printer,
3358                                     TALLOC_CTX *mem_ctx)
3359 {
3360         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3361 }
3362
3363 /*******************************************************************
3364  * fill a notify_info_data with job size
3365  ********************************************************************/
3366
3367 static void spoolss_notify_job_size(int snum,
3368                                     struct spoolss_Notify *data,
3369                                     print_queue_struct *queue,
3370                                     NT_PRINTER_INFO_LEVEL *printer,
3371                                     TALLOC_CTX *mem_ctx)
3372 {
3373         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3374 }
3375
3376 /*******************************************************************
3377  * fill a notify_info_data with page info
3378  ********************************************************************/
3379 static void spoolss_notify_total_pages(int snum,
3380                                 struct spoolss_Notify *data,
3381                                 print_queue_struct *queue,
3382                                 NT_PRINTER_INFO_LEVEL *printer,
3383                                 TALLOC_CTX *mem_ctx)
3384 {
3385         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3386 }
3387
3388 /*******************************************************************
3389  * fill a notify_info_data with pages printed info.
3390  ********************************************************************/
3391 static void spoolss_notify_pages_printed(int snum,
3392                                 struct spoolss_Notify *data,
3393                                 print_queue_struct *queue,
3394                                 NT_PRINTER_INFO_LEVEL *printer,
3395                                 TALLOC_CTX *mem_ctx)
3396 {
3397         /* Add code when back-end tracks this */
3398         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3399 }
3400
3401 /*******************************************************************
3402  Fill a notify_info_data with job position.
3403  ********************************************************************/
3404
3405 static void spoolss_notify_job_position(int snum,
3406                                         struct spoolss_Notify *data,
3407                                         print_queue_struct *queue,
3408                                         NT_PRINTER_INFO_LEVEL *printer,
3409                                         TALLOC_CTX *mem_ctx)
3410 {
3411         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3412 }
3413
3414 /*******************************************************************
3415  Fill a notify_info_data with submitted time.
3416  ********************************************************************/
3417
3418 static void spoolss_notify_submitted_time(int snum,
3419                                           struct spoolss_Notify *data,
3420                                           print_queue_struct *queue,
3421                                           NT_PRINTER_INFO_LEVEL *printer,
3422                                           TALLOC_CTX *mem_ctx)
3423 {
3424         data->data.string.string = NULL;
3425         data->data.string.size = 0;
3426
3427         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3428                                &data->data.string.string,
3429                                &data->data.string.size);
3430
3431 }
3432
3433 struct s_notify_info_data_table
3434 {
3435         enum spoolss_NotifyType type;
3436         enum spoolss_Field field;
3437         const char *name;
3438         enum spoolss_NotifyTable variable_type;
3439         void (*fn) (int snum, struct spoolss_Notify *data,
3440                     print_queue_struct *queue,
3441                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3442 };
3443
3444 /* A table describing the various print notification constants and
3445    whether the notification data is a pointer to a variable sized
3446    buffer, a one value uint32 or a two value uint32. */
3447
3448 static const struct s_notify_info_data_table notify_info_data_table[] =
3449 {
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3476 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3477 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3478 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3489 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3490 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3491 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3492 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3493 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3494 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3495 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3496 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3497 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3498 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3499 };
3500
3501 /*******************************************************************
3502  Return the variable_type of info_data structure.
3503 ********************************************************************/
3504
3505 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3506                                                   enum spoolss_Field field)
3507 {
3508         int i=0;
3509
3510         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3511                 if ( (notify_info_data_table[i].type == type) &&
3512                      (notify_info_data_table[i].field == field) ) {
3513                         return notify_info_data_table[i].variable_type;
3514                 }
3515         }
3516
3517         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3518
3519         return 0;
3520 }
3521
3522 /****************************************************************************
3523 ****************************************************************************/
3524
3525 static bool search_notify(enum spoolss_NotifyType type,
3526                           enum spoolss_Field field,
3527                           int *value)
3528 {
3529         int i;
3530
3531         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3532                 if (notify_info_data_table[i].type == type &&
3533                     notify_info_data_table[i].field == field &&
3534                     notify_info_data_table[i].fn != NULL) {
3535                         *value = i;
3536                         return True;
3537                 }
3538         }
3539
3540         return False;
3541 }
3542
3543 /****************************************************************************
3544 ****************************************************************************/
3545
3546 void construct_info_data(struct spoolss_Notify *info_data,
3547                          enum spoolss_NotifyType type,
3548                          enum spoolss_Field field,
3549                          int id)
3550 {
3551         info_data->type                 = type;
3552         info_data->field                = field;
3553         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3554         info_data->job_id               = id;
3555 }
3556
3557 /*******************************************************************
3558  *
3559  * fill a notify_info struct with info asked
3560  *
3561  ********************************************************************/
3562
3563 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3564                                           struct spoolss_NotifyInfo *info,
3565                                           int snum,
3566                                           const struct spoolss_NotifyOptionType *option_type,
3567                                           uint32_t id,
3568                                           TALLOC_CTX *mem_ctx)
3569 {
3570         int field_num,j;
3571         enum spoolss_NotifyType type;
3572         enum spoolss_Field field;
3573
3574         struct spoolss_Notify *current_data;
3575         NT_PRINTER_INFO_LEVEL *printer = NULL;
3576         print_queue_struct *queue=NULL;
3577
3578         type = option_type->type;
3579
3580         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3581                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3582                 option_type->count, lp_servicename(snum)));
3583
3584         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3585                 return False;
3586
3587         for(field_num=0; field_num < option_type->count; field_num++) {
3588                 field = option_type->fields[field_num];
3589
3590                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3591
3592                 if (!search_notify(type, field, &j) )
3593                         continue;
3594
3595                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3596                                                       struct spoolss_Notify,
3597                                                       info->count + 1);
3598                 if (info->notifies == NULL) {
3599                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3600                         free_a_printer(&printer, 2);
3601                         return False;
3602                 }
3603
3604                 current_data = &info->notifies[info->count];
3605
3606                 construct_info_data(current_data, type, field, id);
3607
3608                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3609                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3610
3611                 notify_info_data_table[j].fn(snum, current_data, queue,
3612                                              printer, mem_ctx);
3613
3614                 info->count++;
3615         }
3616
3617         free_a_printer(&printer, 2);
3618         return True;
3619 }
3620
3621 /*******************************************************************
3622  *
3623  * fill a notify_info struct with info asked
3624  *
3625  ********************************************************************/
3626
3627 static bool construct_notify_jobs_info(print_queue_struct *queue,
3628                                        struct spoolss_NotifyInfo *info,
3629                                        NT_PRINTER_INFO_LEVEL *printer,
3630                                        int snum,
3631                                        const struct spoolss_NotifyOptionType *option_type,
3632                                        uint32_t id,
3633                                        TALLOC_CTX *mem_ctx)
3634 {
3635         int field_num,j;
3636         enum spoolss_NotifyType type;
3637         enum spoolss_Field field;
3638         struct spoolss_Notify *current_data;
3639
3640         DEBUG(4,("construct_notify_jobs_info\n"));
3641
3642         type = option_type->type;
3643
3644         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3645                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3646                 option_type->count));
3647
3648         for(field_num=0; field_num<option_type->count; field_num++) {
3649                 field = option_type->fields[field_num];
3650
3651                 if (!search_notify(type, field, &j) )
3652                         continue;
3653
3654                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3655                                                       struct spoolss_Notify,
3656                                                       info->count + 1);
3657                 if (info->notifies == NULL) {
3658                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3659                         return False;
3660                 }
3661
3662                 current_data=&(info->notifies[info->count]);
3663
3664                 construct_info_data(current_data, type, field, id);
3665                 notify_info_data_table[j].fn(snum, current_data, queue,
3666                                              printer, mem_ctx);
3667                 info->count++;
3668         }
3669
3670         return True;
3671 }
3672
3673 /*
3674  * JFM: The enumeration is not that simple, it's even non obvious.
3675  *
3676  * let's take an example: I want to monitor the PRINTER SERVER for
3677  * the printer's name and the number of jobs currently queued.
3678  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3679  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3680  *
3681  * I have 3 printers on the back of my server.
3682  *
3683  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3684  * structures.
3685  *   Number     Data                    Id
3686  *      1       printer 1 name          1
3687  *      2       printer 1 cjob          1
3688  *      3       printer 2 name          2
3689  *      4       printer 2 cjob          2
3690  *      5       printer 3 name          3
3691  *      6       printer 3 name          3
3692  *
3693  * that's the print server case, the printer case is even worse.
3694  */
3695
3696 /*******************************************************************
3697  *
3698  * enumerate all printers on the printserver
3699  * fill a notify_info struct with info asked
3700  *
3701  ********************************************************************/
3702
3703 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3704                                       struct spoolss_NotifyInfo *info,
3705                                       TALLOC_CTX *mem_ctx)
3706 {
3707         int snum;
3708         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3709         int n_services=lp_numservices();
3710         int i;
3711         struct spoolss_NotifyOption *option;
3712         struct spoolss_NotifyOptionType option_type;
3713
3714         DEBUG(4,("printserver_notify_info\n"));
3715
3716         if (!Printer)
3717                 return WERR_BADFID;
3718
3719         option = Printer->notify.option;
3720
3721         info->version   = 2;
3722         info->notifies  = NULL;
3723         info->count     = 0;
3724
3725         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3726            sending a ffpcn() request first */
3727
3728         if ( !option )
3729                 return WERR_BADFID;
3730
3731         for (i=0; i<option->count; i++) {
3732                 option_type = option->types[i];
3733
3734                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3735                         continue;
3736
3737                 for (snum=0; snum<n_services; snum++)
3738                 {
3739                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3740                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3741                 }
3742         }
3743
3744 #if 0
3745         /*
3746          * Debugging information, don't delete.
3747          */
3748
3749         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3750         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3751         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3752
3753         for (i=0; i<info->count; i++) {
3754                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3755                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3756                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3757         }
3758 #endif
3759
3760         return WERR_OK;
3761 }
3762
3763 /*******************************************************************
3764  *
3765  * fill a notify_info struct with info asked
3766  *
3767  ********************************************************************/
3768
3769 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3770                                   TALLOC_CTX *mem_ctx)
3771 {
3772         int snum;
3773         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3774         int i;
3775         uint32 id;
3776         struct spoolss_NotifyOption *option;
3777         struct spoolss_NotifyOptionType option_type;
3778         int count,j;
3779         print_queue_struct *queue=NULL;
3780         print_status_struct status;
3781
3782         DEBUG(4,("printer_notify_info\n"));
3783
3784         if (!Printer)
3785                 return WERR_BADFID;
3786
3787         option = Printer->notify.option;
3788         id = 0x0;
3789
3790         info->version   = 2;
3791         info->notifies  = NULL;
3792         info->count     = 0;
3793
3794         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3795            sending a ffpcn() request first */
3796
3797         if ( !option )
3798                 return WERR_BADFID;
3799
3800         get_printer_snum(p, hnd, &snum, NULL);
3801
3802         for (i=0; i<option->count; i++) {
3803                 option_type = option->types[i];
3804
3805                 switch (option_type.type) {
3806                 case PRINTER_NOTIFY_TYPE:
3807                         if(construct_notify_printer_info(Printer, info, snum,
3808                                                          &option_type, id,
3809                                                          mem_ctx))
3810                                 id--;
3811                         break;
3812
3813                 case JOB_NOTIFY_TYPE: {
3814                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3815
3816                         count = print_queue_status(snum, &queue, &status);
3817
3818                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3819                                 goto done;
3820
3821                         for (j=0; j<count; j++) {
3822                                 construct_notify_jobs_info(&queue[j], info,
3823                                                            printer, snum,
3824                                                            &option_type,
3825                                                            queue[j].job,
3826                                                            mem_ctx);
3827                         }
3828
3829                         free_a_printer(&printer, 2);
3830
3831                 done:
3832                         SAFE_FREE(queue);
3833                         break;
3834                 }
3835                 }
3836         }
3837
3838         /*
3839          * Debugging information, don't delete.
3840          */
3841         /*
3842         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3843         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3844         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3845
3846         for (i=0; i<info->count; i++) {
3847                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3848                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3849                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3850         }
3851         */
3852         return WERR_OK;
3853 }
3854
3855 /****************************************************************
3856  _spoolss_RouterRefreshPrinterChangeNotify
3857 ****************************************************************/
3858
3859 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3860                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3861 {
3862         POLICY_HND *handle = r->in.handle;
3863         struct spoolss_NotifyInfo *info;
3864
3865         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3866         WERROR result = WERR_BADFID;
3867
3868         /* we always have a spoolss_NotifyInfo struct */
3869         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3870         if (!info) {
3871                 result = WERR_NOMEM;
3872                 goto done;
3873         }
3874
3875         *r->out.info = info;
3876
3877         if (!Printer) {
3878                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3879                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3880                 goto done;
3881         }
3882
3883         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3884
3885         /*
3886          *      We are now using the change value, and
3887          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3888          *      I don't have a global notification system, I'm sending back all the
3889          *      informations even when _NOTHING_ has changed.
3890          */
3891
3892         /* We need to keep track of the change value to send back in
3893            RRPCN replies otherwise our updates are ignored. */
3894
3895         Printer->notify.fnpcn = True;
3896
3897         if (Printer->notify.client_connected) {
3898                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3899                         "Saving change value in request [%x]\n",
3900                         r->in.change_low));
3901                 Printer->notify.change = r->in.change_low;
3902         }
3903
3904         /* just ignore the spoolss_NotifyOption */
3905
3906         switch (Printer->printer_type) {
3907                 case SPLHND_SERVER:
3908                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3909                         break;
3910
3911                 case SPLHND_PRINTER:
3912                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3913                         break;
3914         }
3915
3916         Printer->notify.fnpcn = False;
3917
3918 done:
3919         return result;
3920 }
3921
3922 /********************************************************************
3923  * construct_printer_info_0
3924  * fill a printer_info_0 struct
3925  ********************************************************************/
3926
3927 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3928 {
3929         char *chaine = NULL;
3930         int count;
3931         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3932         counter_printer_0 *session_counter;
3933         uint32 global_counter;
3934         struct tm *t;
3935         time_t setuptime;
3936         print_status_struct status;
3937         TALLOC_CTX *ctx = talloc_tos();
3938
3939         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3940                 return False;
3941
3942         init_unistr(&printer->printername, ntprinter->info_2->printername);
3943
3944         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3945         if (!chaine) {
3946                 free_a_printer(&ntprinter,2);
3947                 return false;
3948         }
3949
3950         count = print_queue_length(snum, &status);
3951
3952         /* check if we already have a counter for this printer */
3953         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3954                 if (session_counter->snum == snum)
3955                         break;
3956         }
3957
3958         init_unistr(&printer->servername, chaine);
3959
3960         /* it's the first time, add it to the list */
3961         if (session_counter==NULL) {
3962                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3963                         free_a_printer(&ntprinter, 2);
3964                         return False;
3965                 }
3966                 ZERO_STRUCTP(session_counter);
3967                 session_counter->snum=snum;
3968                 session_counter->counter=0;
3969                 DLIST_ADD(counter_list, session_counter);
3970         }
3971
3972         /* increment it */
3973         session_counter->counter++;
3974
3975         /* JFM:
3976          * the global_counter should be stored in a TDB as it's common to all the clients
3977          * and should be zeroed on samba startup
3978          */
3979         global_counter=session_counter->counter;
3980         printer->cjobs = count;
3981         printer->total_jobs = 0;
3982         printer->total_bytes = 0;
3983
3984         setuptime = (time_t)ntprinter->info_2->setuptime;
3985         t=gmtime(&setuptime);
3986
3987         printer->year = t->tm_year+1900;
3988         printer->month = t->tm_mon+1;
3989         printer->dayofweek = t->tm_wday;
3990         printer->day = t->tm_mday;
3991         printer->hour = t->tm_hour;
3992         printer->minute = t->tm_min;
3993         printer->second = t->tm_sec;
3994         printer->milliseconds = 0;
3995
3996         printer->global_counter = global_counter;
3997         printer->total_pages = 0;
3998
3999         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4000         printer->major_version = 0x0005;        /* NT 5 */
4001         printer->build_version = 0x0893;        /* build 2195 */
4002
4003         printer->unknown7 = 0x1;
4004         printer->unknown8 = 0x0;
4005         printer->unknown9 = 0x0;
4006         printer->session_counter = session_counter->counter;
4007         printer->unknown11 = 0x0;
4008         printer->printer_errors = 0x0;          /* number of print failure */
4009         printer->unknown13 = 0x0;
4010         printer->unknown14 = 0x1;
4011         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4012         printer->unknown16 =  0x0;
4013         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4014         printer->unknown18 =  0x0;
4015         printer->status = nt_printq_status(status.status);
4016         printer->unknown20 =  0x0;
4017         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4018         printer->unknown22 = 0x0;
4019         printer->unknown23 = 0x6;               /* 6  ???*/
4020         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4021         printer->unknown25 = 0;
4022         printer->unknown26 = 0;
4023         printer->unknown27 = 0;
4024         printer->unknown28 = 0;
4025         printer->unknown29 = 0;
4026
4027         free_a_printer(&ntprinter,2);
4028         return (True);
4029 }
4030
4031 /********************************************************************
4032  * construct_printer_info_1
4033  * fill a printer_info_1 struct
4034  ********************************************************************/
4035 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4036 {
4037         char *chaine = NULL;
4038         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4039         TALLOC_CTX *ctx = talloc_tos();
4040
4041         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4042                 return false;
4043
4044         printer->flags=flags;
4045
4046         if (*ntprinter->info_2->comment == '\0') {
4047                 init_unistr(&printer->comment, lp_comment(snum));
4048                 chaine = talloc_asprintf(ctx,
4049                                 "%s,%s,%s", ntprinter->info_2->printername,
4050                                 ntprinter->info_2->drivername, lp_comment(snum));
4051         }
4052         else {
4053                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4054                 chaine = talloc_asprintf(ctx,
4055                                 "%s,%s,%s", ntprinter->info_2->printername,
4056                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4057         }
4058
4059         if (!chaine) {
4060                 free_a_printer(&ntprinter,2);
4061                 return false;
4062         }
4063
4064         init_unistr(&printer->description, chaine);
4065         init_unistr(&printer->name, ntprinter->info_2->printername);
4066
4067         free_a_printer(&ntprinter,2);
4068
4069         return True;
4070 }
4071
4072 /****************************************************************************
4073  Free a DEVMODE struct.
4074 ****************************************************************************/
4075
4076 static void free_dev_mode(DEVICEMODE *dev)
4077 {
4078         if (dev == NULL)
4079                 return;
4080
4081         SAFE_FREE(dev->dev_private);
4082         SAFE_FREE(dev);
4083 }
4084
4085
4086 /****************************************************************************
4087  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4088  should be valid upon entry
4089 ****************************************************************************/
4090
4091 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4092 {
4093         if ( !devmode || !ntdevmode )
4094                 return False;
4095
4096         init_unistr(&devmode->devicename, ntdevmode->devicename);
4097
4098         init_unistr(&devmode->formname, ntdevmode->formname);
4099
4100         devmode->specversion      = ntdevmode->specversion;
4101         devmode->driverversion    = ntdevmode->driverversion;
4102         devmode->size             = ntdevmode->size;
4103         devmode->driverextra      = ntdevmode->driverextra;
4104         devmode->fields           = ntdevmode->fields;
4105
4106         devmode->orientation      = ntdevmode->orientation;
4107         devmode->papersize        = ntdevmode->papersize;
4108         devmode->paperlength      = ntdevmode->paperlength;
4109         devmode->paperwidth       = ntdevmode->paperwidth;
4110         devmode->scale            = ntdevmode->scale;
4111         devmode->copies           = ntdevmode->copies;
4112         devmode->defaultsource    = ntdevmode->defaultsource;
4113         devmode->printquality     = ntdevmode->printquality;
4114         devmode->color            = ntdevmode->color;
4115         devmode->duplex           = ntdevmode->duplex;
4116         devmode->yresolution      = ntdevmode->yresolution;
4117         devmode->ttoption         = ntdevmode->ttoption;
4118         devmode->collate          = ntdevmode->collate;
4119         devmode->icmmethod        = ntdevmode->icmmethod;
4120         devmode->icmintent        = ntdevmode->icmintent;
4121         devmode->mediatype        = ntdevmode->mediatype;
4122         devmode->dithertype       = ntdevmode->dithertype;
4123
4124         if (ntdevmode->nt_dev_private != NULL) {
4125                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4126                         return False;
4127         }
4128
4129         return True;
4130 }
4131
4132 /****************************************************************************
4133  Create a DEVMODE struct. Returns malloced memory.
4134 ****************************************************************************/
4135
4136 DEVICEMODE *construct_dev_mode(const char *servicename)
4137 {
4138         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4139         DEVICEMODE              *devmode = NULL;
4140
4141         DEBUG(7,("construct_dev_mode\n"));
4142
4143         DEBUGADD(8,("getting printer characteristics\n"));
4144
4145         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4146                 return NULL;
4147
4148         if ( !printer->info_2->devmode ) {
4149                 DEBUG(5, ("BONG! There was no device mode!\n"));
4150                 goto done;
4151         }
4152
4153         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4154                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4155                 goto done;
4156         }
4157
4158         ZERO_STRUCTP(devmode);
4159
4160         DEBUGADD(8,("loading DEVICEMODE\n"));
4161
4162         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4163                 free_dev_mode( devmode );
4164                 devmode = NULL;
4165         }
4166
4167 done:
4168         free_a_printer(&printer,2);
4169
4170         return devmode;
4171 }
4172
4173 /********************************************************************
4174  * construct_printer_info_2
4175  * fill a printer_info_2 struct
4176  ********************************************************************/
4177
4178 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4179 {
4180         int count;
4181         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4182
4183         print_status_struct status;
4184
4185         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4186                 return False;
4187
4188         count = print_queue_length(snum, &status);
4189
4190         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4191         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4192         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4193         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4194         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4195
4196         if (*ntprinter->info_2->comment == '\0')
4197                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4198         else
4199                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4200
4201         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4202         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4203         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4204         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4205         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4206
4207         printer->attributes = ntprinter->info_2->attributes;
4208
4209         printer->priority = ntprinter->info_2->priority;                                /* priority */
4210         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4211         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4212         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4213         printer->status = nt_printq_status(status.status);                      /* status */
4214         printer->cjobs = count;                                                 /* jobs */
4215         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4216
4217         if ( !(printer->devmode = construct_dev_mode(
4218                        lp_const_servicename(snum))) )
4219                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4220
4221         printer->secdesc = NULL;
4222
4223         if ( ntprinter->info_2->secdesc_buf
4224                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4225         {
4226                 /* don't use talloc_steal() here unless you do a deep steal of all
4227                    the SEC_DESC members */
4228
4229                 printer->secdesc = dup_sec_desc( talloc_tos(),
4230                         ntprinter->info_2->secdesc_buf->sd );
4231         }
4232
4233         free_a_printer(&ntprinter, 2);
4234
4235         return True;
4236 }
4237
4238 /********************************************************************
4239  * construct_printer_info_3
4240  * fill a printer_info_3 struct
4241  ********************************************************************/
4242
4243 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4244 {
4245         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4246         PRINTER_INFO_3 *printer = NULL;
4247
4248         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4249                 return False;
4250
4251         *pp_printer = NULL;
4252         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4253                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4254                 free_a_printer(&ntprinter, 2);
4255                 return False;
4256         }
4257
4258         ZERO_STRUCTP(printer);
4259
4260         /* These are the components of the SD we are returning. */
4261
4262         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4263                 /* don't use talloc_steal() here unless you do a deep steal of all
4264                    the SEC_DESC members */
4265
4266                 printer->secdesc = dup_sec_desc( talloc_tos(),
4267                         ntprinter->info_2->secdesc_buf->sd );
4268         }
4269
4270         free_a_printer(&ntprinter, 2);
4271
4272         *pp_printer = printer;
4273         return True;
4274 }
4275
4276 /********************************************************************
4277  * construct_printer_info_4
4278  * fill a printer_info_4 struct
4279  ********************************************************************/
4280
4281 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4282 {
4283         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4284
4285         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4286                 return False;
4287
4288         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4289         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4290         printer->attributes = ntprinter->info_2->attributes;
4291
4292         free_a_printer(&ntprinter, 2);
4293         return True;
4294 }
4295
4296 /********************************************************************
4297  * construct_printer_info_5
4298  * fill a printer_info_5 struct
4299  ********************************************************************/
4300
4301 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4302 {
4303         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4304
4305         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4306                 return False;
4307
4308         init_unistr(&printer->printername, ntprinter->info_2->printername);
4309         init_unistr(&printer->portname, ntprinter->info_2->portname);
4310         printer->attributes = ntprinter->info_2->attributes;
4311
4312         /* these two are not used by NT+ according to MSDN */
4313
4314         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4315         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4316
4317         free_a_printer(&ntprinter, 2);
4318
4319         return True;
4320 }
4321
4322 /********************************************************************
4323  * construct_printer_info_6
4324  * fill a printer_info_6 struct
4325  ********************************************************************/
4326
4327 static bool construct_printer_info_6(Printer_entry *print_hnd,
4328                                      PRINTER_INFO_6 *printer,
4329                                      int snum)
4330 {
4331         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4332         int count;
4333         print_status_struct status;
4334
4335         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4336                                          lp_const_servicename(snum))))
4337                 return False;
4338
4339         count = print_queue_length(snum, &status);
4340
4341         printer->status = nt_printq_status(status.status);
4342
4343         free_a_printer(&ntprinter, 2);
4344
4345         return True;
4346 }
4347
4348 /********************************************************************
4349  * construct_printer_info_7
4350  * fill a printer_info_7 struct
4351  ********************************************************************/
4352
4353 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4354 {
4355         char *guid_str = NULL;
4356         struct GUID guid;
4357
4358         if (is_printer_published(print_hnd, snum, &guid)) {
4359                 if (asprintf(&guid_str, "{%s}",
4360                              GUID_string(talloc_tos(), &guid)) == -1) {
4361                         return false;
4362                 }
4363                 strupper_m(guid_str);
4364                 init_unistr(&printer->guid, guid_str);
4365                 SAFE_FREE(guid_str);
4366                 printer->action = DSPRINT_PUBLISH;
4367         } else {
4368                 init_unistr(&printer->guid, "");
4369                 printer->action = DSPRINT_UNPUBLISH;
4370         }
4371
4372         return True;
4373 }
4374
4375 /********************************************************************
4376  Spoolss_enumprinters.
4377 ********************************************************************/
4378
4379 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4380 {
4381         int snum;
4382         int i;
4383         int n_services=lp_numservices();
4384         PRINTER_INFO_1 *printers=NULL;
4385         PRINTER_INFO_1 current_prt;
4386         WERROR result = WERR_OK;
4387
4388         DEBUG(4,("enum_all_printers_info_1\n"));
4389
4390         for (snum=0; snum<n_services; snum++) {
4391                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4392                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4393
4394                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4395                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4396                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4397                                         *returned=0;
4398                                         return WERR_NOMEM;
4399                                 }
4400                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4401
4402                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4403                                 (*returned)++;
4404                         }
4405                 }
4406         }
4407
4408         /* check the required size. */
4409         for (i=0; i<*returned; i++)
4410                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4411
4412         if (*needed > offered) {
4413                 result = WERR_INSUFFICIENT_BUFFER;
4414                 goto out;
4415         }
4416
4417         if (!rpcbuf_alloc_size(buffer, *needed)) {
4418                 result = WERR_NOMEM;
4419                 goto out;
4420         }
4421
4422         /* fill the buffer with the structures */
4423         for (i=0; i<*returned; i++)
4424                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4425
4426 out:
4427         /* clear memory */
4428
4429         SAFE_FREE(printers);
4430
4431         if ( !W_ERROR_IS_OK(result) )
4432                 *returned = 0;
4433
4434         return result;
4435 }
4436
4437 /********************************************************************
4438  enum_all_printers_info_1_local.
4439 *********************************************************************/
4440
4441 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 {
4443         DEBUG(4,("enum_all_printers_info_1_local\n"));
4444
4445         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4446 }
4447
4448 /********************************************************************
4449  enum_all_printers_info_1_name.
4450 *********************************************************************/
4451
4452 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 {
4454         char *s = name;
4455
4456         DEBUG(4,("enum_all_printers_info_1_name\n"));
4457
4458         if ((name[0] == '\\') && (name[1] == '\\'))
4459                 s = name + 2;
4460
4461         if (is_myname_or_ipaddr(s)) {
4462                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4463         }
4464         else
4465                 return WERR_INVALID_NAME;
4466 }
4467
4468 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4469 /********************************************************************
4470  enum_all_printers_info_1_remote.
4471 *********************************************************************/
4472
4473 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 {
4475         PRINTER_INFO_1 *printer;
4476         fstring printername;
4477         fstring desc;
4478         fstring comment;
4479         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4480         WERROR result = WERR_OK;
4481
4482         /* JFM: currently it's more a place holder than anything else.
4483          * In the spooler world there is a notion of server registration.
4484          * the print servers are registered on the PDC (in the same domain)
4485          *
4486          * We should have a TDB here. The registration is done thru an
4487          * undocumented RPC call.
4488          */
4489
4490         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4491                 return WERR_NOMEM;
4492
4493         *returned=1;
4494
4495         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4496         slprintf(desc, sizeof(desc)-1,"%s", name);
4497         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4498
4499         init_unistr(&printer->description, desc);
4500         init_unistr(&printer->name, printername);
4501         init_unistr(&printer->comment, comment);
4502         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4503
4504         /* check the required size. */
4505         *needed += spoolss_size_printer_info_1(printer);
4506
4507         if (*needed > offered) {
4508                 result = WERR_INSUFFICIENT_BUFFER;
4509                 goto out;
4510         }
4511
4512         if (!rpcbuf_alloc_size(buffer, *needed)) {
4513                 result = WERR_NOMEM;
4514                 goto out;
4515         }
4516
4517         /* fill the buffer with the structures */
4518         smb_io_printer_info_1("", buffer, printer, 0);
4519
4520 out:
4521         /* clear memory */
4522         SAFE_FREE(printer);
4523
4524         if ( !W_ERROR_IS_OK(result) )
4525                 *returned = 0;
4526
4527         return result;
4528 }
4529
4530 #endif
4531
4532 /********************************************************************
4533  enum_all_printers_info_1_network.
4534 *********************************************************************/
4535
4536 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4537 {
4538         char *s = name;
4539
4540         DEBUG(4,("enum_all_printers_info_1_network\n"));
4541
4542         /* If we respond to a enum_printers level 1 on our name with flags
4543            set to PRINTER_ENUM_REMOTE with a list of printers then these
4544            printers incorrectly appear in the APW browse list.
4545            Specifically the printers for the server appear at the workgroup
4546            level where all the other servers in the domain are
4547            listed. Windows responds to this call with a
4548            WERR_CAN_NOT_COMPLETE so we should do the same. */
4549
4550         if (name[0] == '\\' && name[1] == '\\')
4551                  s = name + 2;
4552
4553         if (is_myname_or_ipaddr(s))
4554                  return WERR_CAN_NOT_COMPLETE;
4555
4556         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4557 }
4558
4559 /********************************************************************
4560  * api_spoolss_enumprinters
4561  *
4562  * called from api_spoolss_enumprinters (see this to understand)
4563  ********************************************************************/
4564
4565 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4566 {
4567         int snum;
4568         int i;
4569         int n_services=lp_numservices();
4570         PRINTER_INFO_2 *printers=NULL;
4571         PRINTER_INFO_2 current_prt;
4572         WERROR result = WERR_OK;
4573
4574         *returned = 0;
4575
4576         for (snum=0; snum<n_services; snum++) {
4577                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4578                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4579
4580                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4581                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4582                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4583                                         *returned = 0;
4584                                         return WERR_NOMEM;
4585                                 }
4586
4587                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4588
4589                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4590
4591                                 (*returned)++;
4592                         }
4593                 }
4594         }
4595
4596         /* check the required size. */
4597         for (i=0; i<*returned; i++)
4598                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4599
4600         if (*needed > offered) {
4601                 result = WERR_INSUFFICIENT_BUFFER;
4602                 goto out;
4603         }
4604
4605         if (!rpcbuf_alloc_size(buffer, *needed)) {
4606                 result = WERR_NOMEM;
4607                 goto out;
4608         }
4609
4610         /* fill the buffer with the structures */
4611         for (i=0; i<*returned; i++)
4612                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4613
4614 out:
4615         /* clear memory */
4616
4617         for (i=0; i<*returned; i++)
4618                 free_devmode(printers[i].devmode);
4619
4620         SAFE_FREE(printers);
4621
4622         if ( !W_ERROR_IS_OK(result) )
4623                 *returned = 0;
4624
4625         return result;
4626 }
4627
4628 /********************************************************************
4629  * handle enumeration of printers at level 1
4630  ********************************************************************/
4631
4632 static WERROR enumprinters_level1( uint32 flags, fstring name,
4633                                  RPC_BUFFER *buffer, uint32 offered,
4634                                  uint32 *needed, uint32 *returned)
4635 {
4636         /* Not all the flags are equals */
4637
4638         if (flags & PRINTER_ENUM_LOCAL)
4639                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4640
4641         if (flags & PRINTER_ENUM_NAME)
4642                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4643
4644 #if 0   /* JERRY - disabled for now */
4645         if (flags & PRINTER_ENUM_REMOTE)
4646                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4647 #endif
4648
4649         if (flags & PRINTER_ENUM_NETWORK)
4650                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4651
4652         return WERR_OK; /* NT4sp5 does that */
4653 }
4654
4655 /********************************************************************
4656  * handle enumeration of printers at level 2
4657  ********************************************************************/
4658
4659 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4660                                  RPC_BUFFER *buffer, uint32 offered,
4661                                  uint32 *needed, uint32 *returned)
4662 {
4663         if (flags & PRINTER_ENUM_LOCAL) {
4664                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4665         }
4666
4667         if (flags & PRINTER_ENUM_NAME) {
4668                 if (is_myname_or_ipaddr(canon_servername(servername)))
4669                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4670                 else
4671                         return WERR_INVALID_NAME;
4672         }
4673
4674         if (flags & PRINTER_ENUM_REMOTE)
4675                 return WERR_UNKNOWN_LEVEL;
4676
4677         return WERR_OK;
4678 }
4679
4680 /********************************************************************
4681  * handle enumeration of printers at level 5
4682  ********************************************************************/
4683
4684 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4685                                  RPC_BUFFER *buffer, uint32 offered,
4686                                  uint32 *needed, uint32 *returned)
4687 {
4688 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4689         return WERR_OK;
4690 }
4691
4692 /********************************************************************
4693  * api_spoolss_enumprinters
4694  *
4695  * called from api_spoolss_enumprinters (see this to understand)
4696  ********************************************************************/
4697
4698 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4699 {
4700         uint32 flags = q_u->flags;
4701         UNISTR2 *servername = &q_u->servername;
4702         uint32 level = q_u->level;
4703         RPC_BUFFER *buffer = NULL;
4704         uint32 offered = q_u->offered;
4705         uint32 *needed = &r_u->needed;
4706         uint32 *returned = &r_u->returned;
4707
4708         fstring name;
4709
4710         /* that's an [in out] buffer */
4711
4712         if (!q_u->buffer && (offered!=0)) {
4713                 return WERR_INVALID_PARAM;
4714         }
4715
4716         if (offered > MAX_RPC_DATA_SIZE) {
4717                 return WERR_INVALID_PARAM;
4718         }
4719
4720         rpcbuf_move(q_u->buffer, &r_u->buffer);
4721         buffer = r_u->buffer;
4722
4723         DEBUG(4,("_spoolss_enumprinters\n"));
4724
4725         *needed=0;
4726         *returned=0;
4727
4728         /*
4729          * Level 1:
4730          *          flags==PRINTER_ENUM_NAME
4731          *           if name=="" then enumerates all printers
4732          *           if name!="" then enumerate the printer
4733          *          flags==PRINTER_ENUM_REMOTE
4734          *          name is NULL, enumerate printers
4735          * Level 2: name!="" enumerates printers, name can't be NULL
4736          * Level 3: doesn't exist
4737          * Level 4: does a local registry lookup
4738          * Level 5: same as Level 2
4739          */
4740
4741         unistr2_to_ascii(name, servername, sizeof(name));
4742         strupper_m(name);
4743
4744         switch (level) {
4745         case 1:
4746                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4747         case 2:
4748                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4749         case 5:
4750                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4751         case 3:
4752         case 4:
4753                 break;
4754         }
4755         return WERR_UNKNOWN_LEVEL;
4756 }
4757
4758 /****************************************************************************
4759 ****************************************************************************/
4760
4761 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4762 {
4763         PRINTER_INFO_0 *printer=NULL;
4764         WERROR result = WERR_OK;
4765
4766         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4767                 return WERR_NOMEM;
4768
4769         construct_printer_info_0(print_hnd, printer, snum);
4770
4771         /* check the required size. */
4772         *needed += spoolss_size_printer_info_0(printer);
4773
4774         if (*needed > offered) {
4775                 result = WERR_INSUFFICIENT_BUFFER;
4776                 goto out;
4777         }
4778
4779         if (!rpcbuf_alloc_size(buffer, *needed)) {
4780                 result = WERR_NOMEM;
4781                 goto out;
4782         }
4783
4784         /* fill the buffer with the structures */
4785         smb_io_printer_info_0("", buffer, printer, 0);
4786
4787 out:
4788         /* clear memory */
4789
4790         SAFE_FREE(printer);
4791
4792         return result;
4793 }
4794
4795 /****************************************************************************
4796 ****************************************************************************/
4797
4798 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4799 {
4800         PRINTER_INFO_1 *printer=NULL;
4801         WERROR result = WERR_OK;
4802
4803         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4804                 return WERR_NOMEM;
4805
4806         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4807
4808         /* check the required size. */
4809         *needed += spoolss_size_printer_info_1(printer);
4810
4811         if (*needed > offered) {
4812                 result = WERR_INSUFFICIENT_BUFFER;
4813                 goto out;
4814         }
4815
4816         if (!rpcbuf_alloc_size(buffer, *needed)) {
4817                 result = WERR_NOMEM;
4818                 goto out;
4819         }
4820
4821         /* fill the buffer with the structures */
4822         smb_io_printer_info_1("", buffer, printer, 0);
4823
4824 out:
4825         /* clear memory */
4826         SAFE_FREE(printer);
4827
4828         return result;
4829 }
4830
4831 /****************************************************************************
4832 ****************************************************************************/
4833
4834 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4835 {
4836         PRINTER_INFO_2 *printer=NULL;
4837         WERROR result = WERR_OK;
4838
4839         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4840                 return WERR_NOMEM;
4841
4842         construct_printer_info_2(print_hnd, printer, snum);
4843
4844         /* check the required size. */
4845         *needed += spoolss_size_printer_info_2(printer);
4846
4847         if (*needed > offered) {
4848                 result = WERR_INSUFFICIENT_BUFFER;
4849                 goto out;
4850         }
4851
4852         if (!rpcbuf_alloc_size(buffer, *needed)) {
4853                 result = WERR_NOMEM;
4854                 goto out;
4855         }
4856
4857         /* fill the buffer with the structures */
4858         if (!smb_io_printer_info_2("", buffer, printer, 0))
4859                 result = WERR_NOMEM;
4860
4861 out:
4862         /* clear memory */
4863         free_printer_info_2(printer);
4864
4865         return result;
4866 }
4867
4868 /****************************************************************************
4869 ****************************************************************************/
4870
4871 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4872 {
4873         PRINTER_INFO_3 *printer=NULL;
4874         WERROR result = WERR_OK;
4875
4876         if (!construct_printer_info_3(print_hnd, &printer, snum))
4877                 return WERR_NOMEM;
4878
4879         /* check the required size. */
4880         *needed += spoolss_size_printer_info_3(printer);
4881
4882         if (*needed > offered) {
4883                 result = WERR_INSUFFICIENT_BUFFER;
4884                 goto out;
4885         }
4886
4887         if (!rpcbuf_alloc_size(buffer, *needed)) {
4888                 result = WERR_NOMEM;
4889                 goto out;
4890         }
4891
4892         /* fill the buffer with the structures */
4893         smb_io_printer_info_3("", buffer, printer, 0);
4894
4895 out:
4896         /* clear memory */
4897         free_printer_info_3(printer);
4898
4899         return result;
4900 }
4901
4902 /****************************************************************************
4903 ****************************************************************************/
4904
4905 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4906 {
4907         PRINTER_INFO_4 *printer=NULL;
4908         WERROR result = WERR_OK;
4909
4910         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4911                 return WERR_NOMEM;
4912
4913         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4914                 SAFE_FREE(printer);
4915                 return WERR_NOMEM;
4916         }
4917
4918         /* check the required size. */
4919         *needed += spoolss_size_printer_info_4(printer);
4920
4921         if (*needed > offered) {
4922                 result = WERR_INSUFFICIENT_BUFFER;
4923                 goto out;
4924         }
4925
4926         if (!rpcbuf_alloc_size(buffer, *needed)) {
4927                 result = WERR_NOMEM;
4928                 goto out;
4929         }
4930
4931         /* fill the buffer with the structures */
4932         smb_io_printer_info_4("", buffer, printer, 0);
4933
4934 out:
4935         /* clear memory */
4936         free_printer_info_4(printer);
4937
4938         return result;
4939 }
4940
4941 /****************************************************************************
4942 ****************************************************************************/
4943
4944 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4945 {
4946         PRINTER_INFO_5 *printer=NULL;
4947         WERROR result = WERR_OK;
4948
4949         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4950                 return WERR_NOMEM;
4951
4952         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4953                 free_printer_info_5(printer);
4954                 return WERR_NOMEM;
4955         }
4956
4957         /* check the required size. */
4958         *needed += spoolss_size_printer_info_5(printer);
4959
4960         if (*needed > offered) {
4961                 result = WERR_INSUFFICIENT_BUFFER;
4962                 goto out;
4963         }
4964
4965         if (!rpcbuf_alloc_size(buffer, *needed)) {
4966                 result = WERR_NOMEM;
4967                 goto out;
4968         }
4969
4970         /* fill the buffer with the structures */
4971         smb_io_printer_info_5("", buffer, printer, 0);
4972
4973 out:
4974         /* clear memory */
4975         free_printer_info_5(printer);
4976
4977         return result;
4978 }
4979
4980 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4981                                  int snum,
4982                                  RPC_BUFFER *buffer, uint32 offered,
4983                                  uint32 *needed)
4984 {
4985         PRINTER_INFO_6 *printer;
4986         WERROR result = WERR_OK;
4987
4988         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4989                 return WERR_NOMEM;
4990         }
4991
4992         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4993                 free_printer_info_6(printer);
4994                 return WERR_NOMEM;
4995         }
4996
4997         /* check the required size. */
4998         *needed += spoolss_size_printer_info_6(printer);
4999
5000         if (*needed > offered) {
5001                 result = WERR_INSUFFICIENT_BUFFER;
5002                 goto out;
5003         }
5004
5005         if (!rpcbuf_alloc_size(buffer, *needed)) {
5006                 result = WERR_NOMEM;
5007                 goto out;
5008         }
5009
5010         /* fill the buffer with the structures */
5011         smb_io_printer_info_6("", buffer, printer, 0);
5012
5013 out:
5014         /* clear memory */
5015         free_printer_info_6(printer);
5016
5017         return result;
5018 }
5019
5020 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5021 {
5022         PRINTER_INFO_7 *printer=NULL;
5023         WERROR result = WERR_OK;
5024
5025         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5026                 return WERR_NOMEM;
5027
5028         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5029                 result = WERR_NOMEM;
5030                 goto out;
5031         }
5032
5033         /* check the required size. */
5034         *needed += spoolss_size_printer_info_7(printer);
5035
5036         if (*needed > offered) {
5037                 result = WERR_INSUFFICIENT_BUFFER;
5038                 goto out;
5039         }
5040
5041         if (!rpcbuf_alloc_size(buffer, *needed)) {
5042                 result = WERR_NOMEM;
5043                 goto out;
5044
5045         }
5046
5047         /* fill the buffer with the structures */
5048         smb_io_printer_info_7("", buffer, printer, 0);
5049
5050 out:
5051         /* clear memory */
5052         free_printer_info_7(printer);
5053
5054         return result;
5055 }
5056
5057 /****************************************************************************
5058 ****************************************************************************/
5059
5060 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5061 {
5062         POLICY_HND *handle = &q_u->handle;
5063         uint32 level = q_u->level;
5064         RPC_BUFFER *buffer = NULL;
5065         uint32 offered = q_u->offered;
5066         uint32 *needed = &r_u->needed;
5067         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5068
5069         int snum;
5070
5071         /* that's an [in out] buffer */
5072
5073         if (!q_u->buffer && (offered!=0)) {
5074                 return WERR_INVALID_PARAM;
5075         }
5076
5077         if (offered > MAX_RPC_DATA_SIZE) {
5078                 return WERR_INVALID_PARAM;
5079         }
5080
5081         rpcbuf_move(q_u->buffer, &r_u->buffer);
5082         buffer = r_u->buffer;
5083
5084         *needed=0;
5085
5086         if (!get_printer_snum(p, handle, &snum, NULL))
5087                 return WERR_BADFID;
5088
5089         switch (level) {
5090         case 0:
5091                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5092         case 1:
5093                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5094         case 2:
5095                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5096         case 3:
5097                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5098         case 4:
5099                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5100         case 5:
5101                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5102         case 6:
5103                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5104         case 7:
5105                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5106         }
5107         return WERR_UNKNOWN_LEVEL;
5108 }
5109
5110 /********************************************************************
5111  * fill a DRIVER_INFO_1 struct
5112  ********************************************************************/
5113
5114 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5115 {
5116         init_unistr( &info->name, driver.info_3->name);
5117 }
5118
5119 /********************************************************************
5120  * construct_printer_driver_info_1
5121  ********************************************************************/
5122
5123 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5124 {
5125         NT_PRINTER_INFO_LEVEL *printer = NULL;
5126         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5127
5128         ZERO_STRUCT(driver);
5129
5130         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5131                 return WERR_INVALID_PRINTER_NAME;
5132
5133         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5134                 free_a_printer(&printer, 2);
5135                 return WERR_UNKNOWN_PRINTER_DRIVER;
5136         }
5137
5138         fill_printer_driver_info_1(info, driver, servername, architecture);
5139
5140         free_a_printer(&printer,2);
5141
5142         return WERR_OK;
5143 }
5144
5145 /********************************************************************
5146  * construct_printer_driver_info_2
5147  * fill a printer_info_2 struct
5148  ********************************************************************/
5149
5150 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5151 {
5152         TALLOC_CTX *ctx = talloc_tos();
5153         char *temp = NULL;
5154         const char *cservername = canon_servername(servername);
5155
5156         info->version=driver.info_3->cversion;
5157
5158         init_unistr( &info->name, driver.info_3->name );
5159         init_unistr( &info->architecture, driver.info_3->environment );
5160
5161         if (strlen(driver.info_3->driverpath)) {
5162                 temp = talloc_asprintf(ctx,
5163                                 "\\\\%s%s",
5164                                 cservername,
5165                                 driver.info_3->driverpath);
5166                 init_unistr( &info->driverpath, temp );
5167         } else {
5168                 init_unistr( &info->driverpath, "" );
5169         }
5170
5171         TALLOC_FREE(temp);
5172         if (strlen(driver.info_3->datafile)) {
5173                 temp = talloc_asprintf(ctx,
5174                                 "\\\\%s%s",
5175                                 cservername,
5176                                 driver.info_3->datafile);
5177                 init_unistr( &info->datafile, temp );
5178         } else
5179                 init_unistr( &info->datafile, "" );
5180
5181         TALLOC_FREE(temp);
5182         if (strlen(driver.info_3->configfile)) {
5183                 temp = talloc_asprintf(ctx,
5184                                 "\\\\%s%s",
5185                                 cservername,
5186                                 driver.info_3->configfile);
5187                 init_unistr( &info->configfile, temp );
5188         } else
5189                 init_unistr( &info->configfile, "" );
5190 }
5191
5192 /********************************************************************
5193  * construct_printer_driver_info_2
5194  * fill a printer_info_2 struct
5195  ********************************************************************/
5196
5197 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5198 {
5199         NT_PRINTER_INFO_LEVEL *printer = NULL;
5200         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5201
5202         ZERO_STRUCT(printer);
5203         ZERO_STRUCT(driver);
5204
5205         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5206                 return WERR_INVALID_PRINTER_NAME;
5207
5208         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5209                 free_a_printer(&printer, 2);
5210                 return WERR_UNKNOWN_PRINTER_DRIVER;
5211         }
5212
5213         fill_printer_driver_info_2(info, driver, servername);
5214
5215         free_a_printer(&printer,2);
5216
5217         return WERR_OK;
5218 }
5219
5220 /********************************************************************
5221  * copy a strings array and convert to UNICODE
5222  *
5223  * convert an array of ascii string to a UNICODE string
5224  ********************************************************************/
5225
5226 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5227 {
5228         int i=0;
5229         int j=0;
5230         const char *v;
5231         char *line = NULL;
5232         TALLOC_CTX *ctx = talloc_tos();
5233
5234         DEBUG(6,("init_unistr_array\n"));
5235         *uni_array=NULL;
5236
5237         while (true) {
5238                 if ( !char_array ) {
5239                         v = "";
5240                 } else {
5241                         v = char_array[i];
5242                         if (!v)
5243                                 v = ""; /* hack to handle null lists */
5244                 }
5245
5246                 /* hack to allow this to be used in places other than when generating
5247                    the list of dependent files */
5248
5249                 TALLOC_FREE(line);
5250                 if ( servername ) {
5251                         line = talloc_asprintf(ctx,
5252                                         "\\\\%s%s",
5253                                         canon_servername(servername),
5254                                         v);
5255                 } else {
5256                         line = talloc_strdup(ctx, v);
5257                 }
5258
5259                 if (!line) {
5260                         SAFE_FREE(*uni_array);
5261                         return 0;
5262                 }
5263                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5264
5265                 /* add one extra unit16 for the second terminating NULL */
5266
5267                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5268                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5269                         return 0;
5270                 }
5271
5272                 if ( !strlen(v) )
5273                         break;
5274
5275                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5276                 i++;
5277         }
5278
5279         if (*uni_array) {
5280                 /* special case for ""; we need to add both NULL's here */
5281                 if (!j)
5282                         (*uni_array)[j++]=0x0000;
5283                 (*uni_array)[j]=0x0000;
5284         }
5285
5286         DEBUGADD(6,("last one:done\n"));
5287
5288         /* return size of array in uint16's */
5289
5290         return j+1;
5291 }
5292
5293 /********************************************************************
5294  * construct_printer_info_3
5295  * fill a printer_info_3 struct
5296  ********************************************************************/
5297
5298 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5299 {
5300         char *temp = NULL;
5301         TALLOC_CTX *ctx = talloc_tos();
5302         const char *cservername = canon_servername(servername);
5303
5304         ZERO_STRUCTP(info);
5305
5306         info->version=driver.info_3->cversion;
5307
5308         init_unistr( &info->name, driver.info_3->name );
5309         init_unistr( &info->architecture, driver.info_3->environment );
5310
5311         if (strlen(driver.info_3->driverpath)) {
5312                 temp = talloc_asprintf(ctx,
5313                                 "\\\\%s%s",
5314                                 cservername,
5315                                 driver.info_3->driverpath);
5316                 init_unistr( &info->driverpath, temp );
5317         } else
5318                 init_unistr( &info->driverpath, "" );
5319
5320         TALLOC_FREE(temp);
5321         if (strlen(driver.info_3->datafile)) {
5322                 temp = talloc_asprintf(ctx,
5323                                 "\\\\%s%s",
5324                                 cservername,
5325                                 driver.info_3->datafile);
5326                 init_unistr( &info->datafile, temp );
5327         } else
5328                 init_unistr( &info->datafile, "" );
5329
5330         TALLOC_FREE(temp);
5331         if (strlen(driver.info_3->configfile)) {
5332                 temp = talloc_asprintf(ctx,
5333                                 "\\\\%s%s",
5334                                 cservername,
5335                                 driver.info_3->configfile);
5336                 init_unistr( &info->configfile, temp );
5337         } else
5338                 init_unistr( &info->configfile, "" );
5339
5340         TALLOC_FREE(temp);
5341         if (strlen(driver.info_3->helpfile)) {
5342                 temp = talloc_asprintf(ctx,
5343                                 "\\\\%s%s",
5344                                 cservername,
5345                                 driver.info_3->helpfile);
5346                 init_unistr( &info->helpfile, temp );
5347         } else
5348                 init_unistr( &info->helpfile, "" );
5349
5350         TALLOC_FREE(temp);
5351         init_unistr( &info->monitorname, driver.info_3->monitorname );
5352         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5353
5354         info->dependentfiles=NULL;
5355         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5356 }
5357
5358 /********************************************************************
5359  * construct_printer_info_3
5360  * fill a printer_info_3 struct
5361  ********************************************************************/
5362
5363 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5364 {
5365         NT_PRINTER_INFO_LEVEL *printer = NULL;
5366         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5367         WERROR status;
5368         ZERO_STRUCT(driver);
5369
5370         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5371         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5372         if (!W_ERROR_IS_OK(status))
5373                 return WERR_INVALID_PRINTER_NAME;
5374
5375         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5376         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5377
5378 #if 0   /* JERRY */
5379
5380         /*
5381          * I put this code in during testing.  Helpful when commenting out the
5382          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5383          * as win2k always queries the driver using an infor level of 6.
5384          * I've left it in (but ifdef'd out) because I'll probably
5385          * use it in experimentation again in the future.   --jerry 22/01/2002
5386          */
5387
5388         if (!W_ERROR_IS_OK(status)) {
5389                 /*
5390                  * Is this a W2k client ?
5391                  */
5392                 if (version == 3) {
5393                         /* Yes - try again with a WinNT driver. */
5394                         version = 2;
5395                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5396                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5397                 }
5398 #endif
5399
5400                 if (!W_ERROR_IS_OK(status)) {
5401                         free_a_printer(&printer,2);
5402                         return WERR_UNKNOWN_PRINTER_DRIVER;
5403                 }
5404
5405 #if 0   /* JERRY */
5406         }
5407 #endif
5408
5409
5410         fill_printer_driver_info_3(info, driver, servername);
5411
5412         free_a_printer(&printer,2);
5413
5414         return WERR_OK;
5415 }
5416
5417 /********************************************************************
5418  * construct_printer_info_6
5419  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5420  ********************************************************************/
5421
5422 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5423 {
5424         char *temp = NULL;
5425         fstring nullstr;
5426         TALLOC_CTX *ctx = talloc_tos();
5427         const char *cservername = canon_servername(servername);
5428
5429         ZERO_STRUCTP(info);
5430         memset(&nullstr, '\0', sizeof(fstring));
5431
5432         info->version=driver.info_3->cversion;
5433
5434         init_unistr( &info->name, driver.info_3->name );
5435         init_unistr( &info->architecture, driver.info_3->environment );
5436
5437         if (strlen(driver.info_3->driverpath)) {
5438                 temp = talloc_asprintf(ctx,
5439                                 "\\\\%s%s",
5440                                 cservername,
5441                                 driver.info_3->driverpath);
5442                 init_unistr( &info->driverpath, temp );
5443         } else
5444                 init_unistr( &info->driverpath, "" );
5445
5446         TALLOC_FREE(temp);
5447         if (strlen(driver.info_3->datafile)) {
5448                 temp = talloc_asprintf(ctx,
5449                                 "\\\\%s%s",
5450                                 cservername,
5451                                 driver.info_3->datafile);
5452                 init_unistr( &info->datafile, temp );
5453         } else
5454                 init_unistr( &info->datafile, "" );
5455
5456         TALLOC_FREE(temp);
5457         if (strlen(driver.info_3->configfile)) {
5458                 temp = talloc_asprintf(ctx,
5459                                 "\\\\%s%s",
5460                                 cservername,
5461                                 driver.info_3->configfile);
5462                 init_unistr( &info->configfile, temp );
5463         } else
5464                 init_unistr( &info->configfile, "" );
5465
5466         TALLOC_FREE(temp);
5467         if (strlen(driver.info_3->helpfile)) {
5468                 temp = talloc_asprintf(ctx,
5469                                 "\\\\%s%s",
5470                                 cservername,
5471                                 driver.info_3->helpfile);
5472                 init_unistr( &info->helpfile, temp );
5473         } else
5474                 init_unistr( &info->helpfile, "" );
5475
5476         TALLOC_FREE(temp);
5477         init_unistr( &info->monitorname, driver.info_3->monitorname );
5478         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5479
5480         info->dependentfiles = NULL;
5481         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5482
5483         info->previousdrivernames=NULL;
5484         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5485
5486         info->driver_date=0;
5487
5488         info->padding=0;
5489         info->driver_version_low=0;
5490         info->driver_version_high=0;
5491
5492         init_unistr( &info->mfgname, "");
5493         init_unistr( &info->oem_url, "");
5494         init_unistr( &info->hardware_id, "");
5495         init_unistr( &info->provider, "");
5496 }
5497
5498 /********************************************************************
5499  * construct_printer_info_6
5500  * fill a printer_info_6 struct
5501  ********************************************************************/
5502
5503 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5504               const char *servername, fstring architecture, uint32 version)
5505 {
5506         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5507         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5508         WERROR                          status;
5509
5510         ZERO_STRUCT(driver);
5511
5512         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5513
5514         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5515
5516         if (!W_ERROR_IS_OK(status))
5517                 return WERR_INVALID_PRINTER_NAME;
5518
5519         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5520
5521         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5522
5523         if (!W_ERROR_IS_OK(status))
5524         {
5525                 /*
5526                  * Is this a W2k client ?
5527                  */
5528
5529                 if (version < 3) {
5530                         free_a_printer(&printer,2);
5531                         return WERR_UNKNOWN_PRINTER_DRIVER;
5532                 }
5533
5534                 /* Yes - try again with a WinNT driver. */
5535                 version = 2;
5536                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5537                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5538                 if (!W_ERROR_IS_OK(status)) {
5539                         free_a_printer(&printer,2);
5540                         return WERR_UNKNOWN_PRINTER_DRIVER;
5541                 }
5542         }
5543
5544         fill_printer_driver_info_6(info, driver, servername);
5545
5546         free_a_printer(&printer,2);
5547         free_a_printer_driver(driver, 3);
5548
5549         return WERR_OK;
5550 }
5551
5552 /****************************************************************************
5553 ****************************************************************************/
5554
5555 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5556 {
5557         SAFE_FREE(info->dependentfiles);
5558 }
5559
5560 /****************************************************************************
5561 ****************************************************************************/
5562
5563 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5564 {
5565         SAFE_FREE(info->dependentfiles);
5566 }
5567
5568 /****************************************************************************
5569 ****************************************************************************/
5570
5571 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5572 {
5573         DRIVER_INFO_1 *info=NULL;
5574         WERROR result;
5575
5576         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5577                 return WERR_NOMEM;
5578
5579         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5580         if (!W_ERROR_IS_OK(result))
5581                 goto out;
5582
5583         /* check the required size. */
5584         *needed += spoolss_size_printer_driver_info_1(info);
5585
5586         if (*needed > offered) {
5587                 result = WERR_INSUFFICIENT_BUFFER;
5588                 goto out;
5589         }
5590
5591         if (!rpcbuf_alloc_size(buffer, *needed)) {
5592                 result = WERR_NOMEM;
5593                 goto out;
5594         }
5595
5596         /* fill the buffer with the structures */
5597         smb_io_printer_driver_info_1("", buffer, info, 0);
5598
5599 out:
5600         /* clear memory */
5601         SAFE_FREE(info);
5602
5603         return result;
5604 }
5605
5606 /****************************************************************************
5607 ****************************************************************************/
5608
5609 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5610 {
5611         DRIVER_INFO_2 *info=NULL;
5612         WERROR result;
5613
5614         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5615                 return WERR_NOMEM;
5616
5617         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5618         if (!W_ERROR_IS_OK(result))
5619                 goto out;
5620
5621         /* check the required size. */
5622         *needed += spoolss_size_printer_driver_info_2(info);
5623
5624         if (*needed > offered) {
5625                 result = WERR_INSUFFICIENT_BUFFER;
5626                 goto out;
5627         }
5628
5629         if (!rpcbuf_alloc_size(buffer, *needed)) {
5630                 result = WERR_NOMEM;
5631                 goto out;
5632         }
5633
5634         /* fill the buffer with the structures */
5635         smb_io_printer_driver_info_2("", buffer, info, 0);
5636
5637 out:
5638         /* clear memory */
5639         SAFE_FREE(info);
5640
5641         return result;
5642 }
5643
5644 /****************************************************************************
5645 ****************************************************************************/
5646
5647 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5648 {
5649         DRIVER_INFO_3 info;
5650         WERROR result;
5651
5652         ZERO_STRUCT(info);
5653
5654         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5655         if (!W_ERROR_IS_OK(result))
5656                 goto out;
5657
5658         /* check the required size. */
5659         *needed += spoolss_size_printer_driver_info_3(&info);
5660
5661         if (*needed > offered) {
5662                 result = WERR_INSUFFICIENT_BUFFER;
5663                 goto out;
5664         }
5665
5666         if (!rpcbuf_alloc_size(buffer, *needed)) {
5667                 result = WERR_NOMEM;
5668                 goto out;
5669         }
5670
5671         /* fill the buffer with the structures */
5672         smb_io_printer_driver_info_3("", buffer, &info, 0);
5673
5674 out:
5675         free_printer_driver_info_3(&info);
5676
5677         return result;
5678 }
5679
5680 /****************************************************************************
5681 ****************************************************************************/
5682
5683 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5684 {
5685         DRIVER_INFO_6 info;
5686         WERROR result;
5687
5688         ZERO_STRUCT(info);
5689
5690         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5691         if (!W_ERROR_IS_OK(result))
5692                 goto out;
5693
5694         /* check the required size. */
5695         *needed += spoolss_size_printer_driver_info_6(&info);
5696
5697         if (*needed > offered) {
5698                 result = WERR_INSUFFICIENT_BUFFER;
5699                 goto out;
5700         }
5701
5702         if (!rpcbuf_alloc_size(buffer, *needed)) {
5703                 result = WERR_NOMEM;
5704                 goto out;
5705         }
5706
5707         /* fill the buffer with the structures */
5708         smb_io_printer_driver_info_6("", buffer, &info, 0);
5709
5710 out:
5711         free_printer_driver_info_6(&info);
5712
5713         return result;
5714 }
5715
5716 /****************************************************************************
5717 ****************************************************************************/
5718
5719 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5720 {
5721         POLICY_HND *handle = &q_u->handle;
5722         UNISTR2 *uni_arch = &q_u->architecture;
5723         uint32 level = q_u->level;
5724         uint32 clientmajorversion = q_u->clientmajorversion;
5725         RPC_BUFFER *buffer = NULL;
5726         uint32 offered = q_u->offered;
5727         uint32 *needed = &r_u->needed;
5728         uint32 *servermajorversion = &r_u->servermajorversion;
5729         uint32 *serverminorversion = &r_u->serverminorversion;
5730         Printer_entry *printer;
5731
5732         fstring servername;
5733         fstring architecture;
5734         int snum;
5735
5736         /* that's an [in out] buffer */
5737
5738         if (!q_u->buffer && (offered!=0)) {
5739                 return WERR_INVALID_PARAM;
5740         }
5741
5742         if (offered > MAX_RPC_DATA_SIZE) {
5743                 return WERR_INVALID_PARAM;
5744         }
5745
5746         rpcbuf_move(q_u->buffer, &r_u->buffer);
5747         buffer = r_u->buffer;
5748
5749         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5750
5751         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5752                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5753                 return WERR_INVALID_PRINTER_NAME;
5754         }
5755
5756         *needed = 0;
5757         *servermajorversion = 0;
5758         *serverminorversion = 0;
5759
5760         fstrcpy(servername, get_server_name( printer ));
5761         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5762
5763         if (!get_printer_snum(p, handle, &snum, NULL))
5764                 return WERR_BADFID;
5765
5766         switch (level) {
5767         case 1:
5768                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5769         case 2:
5770                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5771         case 3:
5772                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5773         case 6:
5774                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5775 #if 0   /* JERRY */
5776         case 101:
5777                 /* apparently this call is the equivalent of
5778                    EnumPrinterDataEx() for the DsDriver key */
5779                 break;
5780 #endif
5781         }
5782
5783         return WERR_UNKNOWN_LEVEL;
5784 }
5785
5786
5787 /****************************************************************
5788  _spoolss_StartPagePrinter
5789 ****************************************************************/
5790
5791 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5792                                  struct spoolss_StartPagePrinter *r)
5793 {
5794         POLICY_HND *handle = r->in.handle;
5795
5796         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5797
5798         if (!Printer) {
5799                 DEBUG(3,("_spoolss_StartPagePrinter: "
5800                         "Error in startpageprinter printer handle\n"));
5801                 return WERR_BADFID;
5802         }
5803
5804         Printer->page_started=True;
5805         return WERR_OK;
5806 }
5807
5808 /****************************************************************
5809  _spoolss_EndPagePrinter
5810 ****************************************************************/
5811
5812 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5813                                struct spoolss_EndPagePrinter *r)
5814 {
5815         POLICY_HND *handle = r->in.handle;
5816         int snum;
5817
5818         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5819
5820         if (!Printer) {
5821                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5822                         OUR_HANDLE(handle)));
5823                 return WERR_BADFID;
5824         }
5825
5826         if (!get_printer_snum(p, handle, &snum, NULL))
5827                 return WERR_BADFID;
5828
5829         Printer->page_started=False;
5830         print_job_endpage(snum, Printer->jobid);
5831
5832         return WERR_OK;
5833 }
5834
5835 /****************************************************************
5836  _spoolss_StartDocPrinter
5837 ****************************************************************/
5838
5839 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5840                                 struct spoolss_StartDocPrinter *r)
5841 {
5842         POLICY_HND *handle = r->in.handle;
5843         uint32_t *jobid = r->out.job_id;
5844         struct spoolss_DocumentInfo1 *info_1;
5845         int snum;
5846         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5847
5848         if (!Printer) {
5849                 DEBUG(2,("_spoolss_StartDocPrinter: "
5850                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5851                 return WERR_BADFID;
5852         }
5853
5854         if (r->in.level != 1) {
5855                 return WERR_UNKNOWN_LEVEL;
5856         }
5857
5858         info_1 = r->in.info.info1;
5859
5860         /*
5861          * a nice thing with NT is it doesn't listen to what you tell it.
5862          * when asked to send _only_ RAW datas, it tries to send datas
5863          * in EMF format.
5864          *
5865          * So I add checks like in NT Server ...
5866          */
5867
5868         if (info_1->datatype) {
5869                 if (strcmp(info_1->datatype, "RAW") != 0) {
5870                         (*jobid)=0;
5871                         return WERR_INVALID_DATATYPE;
5872                 }
5873         }
5874
5875         /* get the share number of the printer */
5876         if (!get_printer_snum(p, handle, &snum, NULL)) {
5877                 return WERR_BADFID;
5878         }
5879
5880         Printer->jobid = print_job_start(p->server_info, snum,
5881                                          info_1->document_name,
5882                                          Printer->nt_devmode);
5883
5884         /* An error occured in print_job_start() so return an appropriate
5885            NT error code. */
5886
5887         if (Printer->jobid == -1) {
5888                 return map_werror_from_unix(errno);
5889         }
5890
5891         Printer->document_started=True;
5892         (*jobid) = Printer->jobid;
5893
5894         return WERR_OK;
5895 }
5896
5897 /****************************************************************
5898  _spoolss_EndDocPrinter
5899 ****************************************************************/
5900
5901 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5902                               struct spoolss_EndDocPrinter *r)
5903 {
5904         POLICY_HND *handle = r->in.handle;
5905
5906         return _spoolss_enddocprinter_internal(p, handle);
5907 }
5908
5909 /****************************************************************
5910  _spoolss_WritePrinter
5911 ****************************************************************/
5912
5913 WERROR _spoolss_WritePrinter(pipes_struct *p,
5914                              struct spoolss_WritePrinter *r)
5915 {
5916         POLICY_HND *handle = r->in.handle;
5917         uint32 buffer_size = r->in._data_size;
5918         uint8 *buffer = r->in.data.data;
5919         uint32 *buffer_written = &r->in._data_size;
5920         int snum;
5921         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5922
5923         if (!Printer) {
5924                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5925                         OUR_HANDLE(handle)));
5926                 *r->out.num_written = r->in._data_size;
5927                 return WERR_BADFID;
5928         }
5929
5930         if (!get_printer_snum(p, handle, &snum, NULL))
5931                 return WERR_BADFID;
5932
5933         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5934                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5935         if (*buffer_written == (uint32)-1) {
5936                 *r->out.num_written = 0;
5937                 if (errno == ENOSPC)
5938                         return WERR_NO_SPOOL_SPACE;
5939                 else
5940                         return WERR_ACCESS_DENIED;
5941         }
5942
5943         *r->out.num_written = r->in._data_size;
5944
5945         return WERR_OK;
5946 }
5947
5948 /********************************************************************
5949  * api_spoolss_getprinter
5950  * called from the spoolss dispatcher
5951  *
5952  ********************************************************************/
5953
5954 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5955                               pipes_struct *p)
5956 {
5957         int snum;
5958         WERROR errcode = WERR_BADFUNC;
5959         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5960
5961         if (!Printer) {
5962                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5963                 return WERR_BADFID;
5964         }
5965
5966         if (!get_printer_snum(p, handle, &snum, NULL))
5967                 return WERR_BADFID;
5968
5969         switch (command) {
5970         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5971                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5972                         errcode = WERR_OK;
5973                 }
5974                 break;
5975         case SPOOLSS_PRINTER_CONTROL_RESUME:
5976         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5977                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5978                         errcode = WERR_OK;
5979                 }
5980                 break;
5981         case SPOOLSS_PRINTER_CONTROL_PURGE:
5982                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5983                         errcode = WERR_OK;
5984                 }
5985                 break;
5986         default:
5987                 return WERR_UNKNOWN_LEVEL;
5988         }
5989
5990         return errcode;
5991 }
5992
5993
5994 /****************************************************************
5995  _spoolss_AbortPrinter
5996  * From MSDN: "Deletes printer's spool file if printer is configured
5997  * for spooling"
5998 ****************************************************************/
5999
6000 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6001                              struct spoolss_AbortPrinter *r)
6002 {
6003         POLICY_HND      *handle = r->in.handle;
6004         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6005         int             snum;
6006         WERROR          errcode = WERR_OK;
6007
6008         if (!Printer) {
6009                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6010                         OUR_HANDLE(handle)));
6011                 return WERR_BADFID;
6012         }
6013
6014         if (!get_printer_snum(p, handle, &snum, NULL))
6015                 return WERR_BADFID;
6016
6017         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6018
6019         return errcode;
6020 }
6021
6022 /********************************************************************
6023  * called by spoolss_api_setprinter
6024  * when updating a printer description
6025  ********************************************************************/
6026
6027 static WERROR update_printer_sec(POLICY_HND *handle,
6028                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6029 {
6030         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6031         WERROR result;
6032         int snum;
6033
6034         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6035
6036         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6037                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6038                          OUR_HANDLE(handle)));
6039
6040                 result = WERR_BADFID;
6041                 goto done;
6042         }
6043
6044         if (!secdesc_ctr) {
6045                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6046                 result = WERR_INVALID_PARAM;
6047                 goto done;
6048         }
6049
6050         /* Check the user has permissions to change the security
6051            descriptor.  By experimentation with two NT machines, the user
6052            requires Full Access to the printer to change security
6053            information. */
6054
6055         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6056                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6057                 result = WERR_ACCESS_DENIED;
6058                 goto done;
6059         }
6060
6061         /* NT seems to like setting the security descriptor even though
6062            nothing may have actually changed. */
6063
6064         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6065                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6066                 result = WERR_BADFID;
6067                 goto done;
6068         }
6069
6070         if (DEBUGLEVEL >= 10) {
6071                 SEC_ACL *the_acl;
6072                 int i;
6073
6074                 the_acl = old_secdesc_ctr->sd->dacl;
6075                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6076                            PRINTERNAME(snum), the_acl->num_aces));
6077
6078                 for (i = 0; i < the_acl->num_aces; i++) {
6079                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6080                                            &the_acl->aces[i].trustee),
6081                                   the_acl->aces[i].access_mask));
6082                 }
6083
6084                 the_acl = secdesc_ctr->sd->dacl;
6085
6086                 if (the_acl) {
6087                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6088                                    PRINTERNAME(snum), the_acl->num_aces));
6089
6090                         for (i = 0; i < the_acl->num_aces; i++) {
6091                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6092                                                    &the_acl->aces[i].trustee),
6093                                            the_acl->aces[i].access_mask));
6094                         }
6095                 } else {
6096                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6097                 }
6098         }
6099
6100         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6101         if (!new_secdesc_ctr) {
6102                 result = WERR_NOMEM;
6103                 goto done;
6104         }
6105
6106         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6107                 result = WERR_OK;
6108                 goto done;
6109         }
6110
6111         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6112
6113  done:
6114
6115         return result;
6116 }
6117
6118 /********************************************************************
6119  Canonicalize printer info from a client
6120
6121  ATTN: It does not matter what we set the servername to hear
6122  since we do the necessary work in get_a_printer() to set it to
6123  the correct value based on what the client sent in the
6124  _spoolss_open_printer_ex().
6125  ********************************************************************/
6126
6127 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6128 {
6129         fstring printername;
6130         const char *p;
6131
6132         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6133                 "portname=%s drivername=%s comment=%s location=%s\n",
6134                 info->servername, info->printername, info->sharename,
6135                 info->portname, info->drivername, info->comment, info->location));
6136
6137         /* we force some elements to "correct" values */
6138         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6139         fstrcpy(info->sharename, lp_servicename(snum));
6140
6141         /* check to see if we allow printername != sharename */
6142
6143         if ( lp_force_printername(snum) ) {
6144                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6145                         global_myname(), info->sharename );
6146         } else {
6147
6148                 /* make sure printername is in \\server\printername format */
6149
6150                 fstrcpy( printername, info->printername );
6151                 p = printername;
6152                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6153                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6154                                 p++;
6155                 }
6156
6157                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6158                          global_myname(), p );
6159         }
6160
6161         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6162         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6163
6164
6165
6166         return True;
6167 }
6168
6169 /****************************************************************************
6170 ****************************************************************************/
6171
6172 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6173 {
6174         char *cmd = lp_addport_cmd();
6175         char *command = NULL;
6176         int ret;
6177         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6178         bool is_print_op = False;
6179
6180         if ( !*cmd ) {
6181                 return WERR_ACCESS_DENIED;
6182         }
6183
6184         command = talloc_asprintf(ctx,
6185                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6186         if (!command) {
6187                 return WERR_NOMEM;
6188         }
6189
6190         if ( token )
6191                 is_print_op = user_has_privileges( token, &se_printop );
6192
6193         DEBUG(10,("Running [%s]\n", command));
6194
6195         /********* BEGIN SePrintOperatorPrivilege **********/
6196
6197         if ( is_print_op )
6198                 become_root();
6199
6200         ret = smbrun(command, NULL);
6201
6202         if ( is_print_op )
6203                 unbecome_root();
6204
6205         /********* END SePrintOperatorPrivilege **********/
6206
6207         DEBUGADD(10,("returned [%d]\n", ret));
6208
6209         TALLOC_FREE(command);
6210
6211         if ( ret != 0 ) {
6212                 return WERR_ACCESS_DENIED;
6213         }
6214
6215         return WERR_OK;
6216 }
6217
6218 /****************************************************************************
6219 ****************************************************************************/
6220
6221 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6222 {
6223         char *cmd = lp_addprinter_cmd();
6224         char **qlines;
6225         char *command = NULL;
6226         int numlines;
6227         int ret;
6228         int fd;
6229         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6230         bool is_print_op = False;
6231         char *remote_machine = talloc_strdup(ctx, "%m");
6232
6233         if (!remote_machine) {
6234                 return false;
6235         }
6236         remote_machine = talloc_sub_basic(ctx,
6237                                 current_user_info.smb_name,
6238                                 current_user_info.domain,
6239                                 remote_machine);
6240         if (!remote_machine) {
6241                 return false;
6242         }
6243
6244         command = talloc_asprintf(ctx,
6245                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6246                         cmd, printer->info_2->printername, printer->info_2->sharename,
6247                         printer->info_2->portname, printer->info_2->drivername,
6248                         printer->info_2->location, printer->info_2->comment, remote_machine);
6249         if (!command) {
6250                 return false;
6251         }
6252
6253         if ( token )
6254                 is_print_op = user_has_privileges( token, &se_printop );
6255
6256         DEBUG(10,("Running [%s]\n", command));
6257
6258         /********* BEGIN SePrintOperatorPrivilege **********/
6259
6260         if ( is_print_op )
6261                 become_root();
6262
6263         if ( (ret = smbrun(command, &fd)) == 0 ) {
6264                 /* Tell everyone we updated smb.conf. */
6265                 message_send_all(smbd_messaging_context(),
6266                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6267         }
6268
6269         if ( is_print_op )
6270                 unbecome_root();
6271
6272         /********* END SePrintOperatorPrivilege **********/
6273
6274         DEBUGADD(10,("returned [%d]\n", ret));
6275
6276         TALLOC_FREE(command);
6277         TALLOC_FREE(remote_machine);
6278
6279         if ( ret != 0 ) {
6280                 if (fd != -1)
6281                         close(fd);
6282                 return False;
6283         }
6284
6285         /* reload our services immediately */
6286         reload_services( False );
6287
6288         numlines = 0;
6289         /* Get lines and convert them back to dos-codepage */
6290         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6291         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6292         close(fd);
6293
6294         /* Set the portname to what the script says the portname should be. */
6295         /* but don't require anything to be return from the script exit a good error code */
6296
6297         if (numlines) {
6298                 /* Set the portname to what the script says the portname should be. */
6299                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6300                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6301         }
6302
6303         TALLOC_FREE(qlines);
6304         return True;
6305 }
6306
6307
6308 /********************************************************************
6309  * Called by spoolss_api_setprinter
6310  * when updating a printer description.
6311  ********************************************************************/
6312
6313 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6314                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6315                              struct spoolss_DeviceMode *devmode)
6316 {
6317         int snum;
6318         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6319         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6320         WERROR result;
6321         UNISTR2 buffer;
6322         fstring asc_buffer;
6323
6324         DEBUG(8,("update_printer\n"));
6325
6326         result = WERR_OK;
6327
6328         if (!Printer) {
6329                 result = WERR_BADFID;
6330                 goto done;
6331         }
6332
6333         if (!get_printer_snum(p, handle, &snum, NULL)) {
6334                 result = WERR_BADFID;
6335                 goto done;
6336         }
6337
6338         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6339             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6340                 result = WERR_BADFID;
6341                 goto done;
6342         }
6343
6344         DEBUGADD(8,("Converting info_2 struct\n"));
6345
6346         /*
6347          * convert_printer_info converts the incoming
6348          * info from the client and overwrites the info
6349          * just read from the tdb in the pointer 'printer'.
6350          */
6351
6352         if (!convert_printer_info_new(info_ctr, printer)) {
6353                 result =  WERR_NOMEM;
6354                 goto done;
6355         }
6356
6357         if (devmode) {
6358                 /* we have a valid devmode
6359                    convert it and link it*/
6360
6361                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6362                 if (!convert_devicemode_new(printer->info_2->printername,
6363                                             devmode,
6364                                             &printer->info_2->devmode)) {
6365                         result =  WERR_NOMEM;
6366                         goto done;
6367                 }
6368         }
6369
6370         /* Do sanity check on the requested changes for Samba */
6371
6372         if (!check_printer_ok(printer->info_2, snum)) {
6373                 result = WERR_INVALID_PARAM;
6374                 goto done;
6375         }
6376
6377         /* FIXME!!! If the driver has changed we really should verify that
6378            it is installed before doing much else   --jerry */
6379
6380         /* Check calling user has permission to update printer description */
6381
6382         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6383                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6384                 result = WERR_ACCESS_DENIED;
6385                 goto done;
6386         }
6387
6388         /* Call addprinter hook */
6389         /* Check changes to see if this is really needed */
6390
6391         if ( *lp_addprinter_cmd()
6392                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6393                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6394                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6395                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6396         {
6397                 /* add_printer_hook() will call reload_services() */
6398
6399                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6400                                        printer) ) {
6401                         result = WERR_ACCESS_DENIED;
6402                         goto done;
6403                 }
6404         }
6405
6406         /*
6407          * When a *new* driver is bound to a printer, the drivername is used to
6408          * lookup previously saved driver initialization info, which is then
6409          * bound to the printer, simulating what happens in the Windows arch.
6410          */
6411         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6412         {
6413                 if (!set_driver_init(printer, 2))
6414                 {
6415                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6416                                 printer->info_2->drivername));
6417                 }
6418
6419                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6420                         printer->info_2->drivername));
6421
6422                 notify_printer_driver(snum, printer->info_2->drivername);
6423         }
6424
6425         /*
6426          * flag which changes actually occured.  This is a small subset of
6427          * all the possible changes.  We also have to update things in the
6428          * DsSpooler key.
6429          */
6430
6431         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6432                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6433                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6434                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6435
6436                 notify_printer_comment(snum, printer->info_2->comment);
6437         }
6438
6439         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6440                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6441                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6442                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6443
6444                 notify_printer_sharename(snum, printer->info_2->sharename);
6445         }
6446
6447         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6448                 char *pname;
6449
6450                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6451                         pname++;
6452                 else
6453                         pname = printer->info_2->printername;
6454
6455
6456                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6457                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6458                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6459
6460                 notify_printer_printername( snum, pname );
6461         }
6462
6463         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6464                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6465                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6466                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6467
6468                 notify_printer_port(snum, printer->info_2->portname);
6469         }
6470
6471         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6472                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6473                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6474                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475
6476                 notify_printer_location(snum, printer->info_2->location);
6477         }
6478
6479         /* here we need to update some more DsSpooler keys */
6480         /* uNCName, serverName, shortServerName */
6481
6482         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6483         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6484                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6485         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6486                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6487
6488         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6489                  global_myname(), printer->info_2->sharename );
6490         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6491         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6492                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6493
6494         /* Update printer info */
6495         result = mod_a_printer(printer, 2);
6496
6497 done:
6498         free_a_printer(&printer, 2);
6499         free_a_printer(&old_printer, 2);
6500
6501
6502         return result;
6503 }
6504
6505 /****************************************************************************
6506 ****************************************************************************/
6507 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6508                                            struct spoolss_SetPrinterInfo7 *info7)
6509 {
6510 #ifdef HAVE_ADS
6511         int snum;
6512         Printer_entry *Printer;
6513
6514         if ( lp_security() != SEC_ADS ) {
6515                 return WERR_UNKNOWN_LEVEL;
6516         }
6517
6518         Printer = find_printer_index_by_hnd(p, handle);
6519
6520         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6521
6522         if (!Printer)
6523                 return WERR_BADFID;
6524
6525         if (!get_printer_snum(p, handle, &snum, NULL))
6526                 return WERR_BADFID;
6527
6528         nt_printer_publish(Printer, snum, info7->action);
6529
6530         return WERR_OK;
6531 #else
6532         return WERR_UNKNOWN_LEVEL;
6533 #endif
6534 }
6535
6536 /****************************************************************
6537  _spoolss_SetPrinter
6538 ****************************************************************/
6539
6540 WERROR _spoolss_SetPrinter(pipes_struct *p,
6541                            struct spoolss_SetPrinter *r)
6542 {
6543         POLICY_HND *handle = r->in.handle;
6544         WERROR result;
6545
6546         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6547
6548         if (!Printer) {
6549                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6550                         OUR_HANDLE(handle)));
6551                 return WERR_BADFID;
6552         }
6553
6554         /* check the level */
6555         switch (r->in.info_ctr->level) {
6556                 case 0:
6557                         return control_printer(handle, r->in.command, p);
6558                 case 2:
6559                         result = update_printer(p, handle,
6560                                                 r->in.info_ctr,
6561                                                 r->in.devmode_ctr->devmode);
6562                         if (!W_ERROR_IS_OK(result))
6563                                 return result;
6564                         if (r->in.secdesc_ctr->sd)
6565                                 result = update_printer_sec(handle, p,
6566                                                             r->in.secdesc_ctr);
6567                         return result;
6568                 case 3:
6569                         return update_printer_sec(handle, p,
6570                                                   r->in.secdesc_ctr);
6571                 case 7:
6572                         return publish_or_unpublish_printer(p, handle,
6573                                                             r->in.info_ctr->info.info7);
6574                 default:
6575                         return WERR_UNKNOWN_LEVEL;
6576         }
6577 }
6578
6579 /****************************************************************
6580  _spoolss_FindClosePrinterNotify
6581 ****************************************************************/
6582
6583 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6584                                        struct spoolss_FindClosePrinterNotify *r)
6585 {
6586         POLICY_HND *handle = r->in.handle;
6587         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6588
6589         if (!Printer) {
6590                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6591                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6592                 return WERR_BADFID;
6593         }
6594
6595         if (Printer->notify.client_connected==True) {
6596                 int snum = -1;
6597
6598                 if ( Printer->printer_type == SPLHND_SERVER)
6599                         snum = -1;
6600                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6601                                 !get_printer_snum(p, handle, &snum, NULL) )
6602                         return WERR_BADFID;
6603
6604                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6605         }
6606
6607         Printer->notify.flags=0;
6608         Printer->notify.options=0;
6609         Printer->notify.localmachine[0]='\0';
6610         Printer->notify.printerlocal=0;
6611         TALLOC_FREE(Printer->notify.option);
6612         Printer->notify.client_connected=False;
6613
6614         return WERR_OK;
6615 }
6616
6617 /****************************************************************
6618  _spoolss_AddJob
6619 ****************************************************************/
6620
6621 WERROR _spoolss_AddJob(pipes_struct *p,
6622                        struct spoolss_AddJob *r)
6623 {
6624         if (!r->in.buffer && (r->in.offered != 0)) {
6625                 return WERR_INVALID_PARAM;
6626         }
6627
6628         /* this is what a NT server returns for AddJob. AddJob must fail on
6629          * non-local printers */
6630
6631         if (r->in.level != 1) {
6632                 return WERR_UNKNOWN_LEVEL;
6633         }
6634
6635         return WERR_INVALID_PARAM;
6636 }
6637
6638 /****************************************************************************
6639 ****************************************************************************/
6640
6641 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6642                             int position, int snum,
6643                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6644 {
6645         struct tm *t;
6646
6647         t=gmtime(&queue->time);
6648
6649         job_info->jobid=queue->job;
6650         init_unistr(&job_info->printername, lp_servicename(snum));
6651         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6652         init_unistr(&job_info->username, queue->fs_user);
6653         init_unistr(&job_info->document, queue->fs_file);
6654         init_unistr(&job_info->datatype, "RAW");
6655         init_unistr(&job_info->text_status, "");
6656         job_info->status=nt_printj_status(queue->status);
6657         job_info->priority=queue->priority;
6658         job_info->position=position;
6659         job_info->totalpages=queue->page_count;
6660         job_info->pagesprinted=0;
6661
6662         make_systemtime(&job_info->submitted, t);
6663 }
6664
6665 /****************************************************************************
6666 ****************************************************************************/
6667
6668 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6669                             int position, int snum,
6670                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6671                             DEVICEMODE *devmode)
6672 {
6673         struct tm *t;
6674
6675         t=gmtime(&queue->time);
6676
6677         job_info->jobid=queue->job;
6678
6679         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6680
6681         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6682         init_unistr(&job_info->username, queue->fs_user);
6683         init_unistr(&job_info->document, queue->fs_file);
6684         init_unistr(&job_info->notifyname, queue->fs_user);
6685         init_unistr(&job_info->datatype, "RAW");
6686         init_unistr(&job_info->printprocessor, "winprint");
6687         init_unistr(&job_info->parameters, "");
6688         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6689         init_unistr(&job_info->text_status, "");
6690
6691 /* and here the security descriptor */
6692
6693         job_info->status=nt_printj_status(queue->status);
6694         job_info->priority=queue->priority;
6695         job_info->position=position;
6696         job_info->starttime=0;
6697         job_info->untiltime=0;
6698         job_info->totalpages=queue->page_count;
6699         job_info->size=queue->size;
6700         make_systemtime(&(job_info->submitted), t);
6701         job_info->timeelapsed=0;
6702         job_info->pagesprinted=0;
6703
6704         job_info->devmode = devmode;
6705
6706         return (True);
6707 }
6708
6709 /****************************************************************************
6710  Enumjobs at level 1.
6711 ****************************************************************************/
6712
6713 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6714                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6715                               RPC_BUFFER *buffer, uint32 offered,
6716                               uint32 *needed, uint32 *returned)
6717 {
6718         JOB_INFO_1 *info;
6719         int i;
6720         WERROR result = WERR_OK;
6721
6722         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6723         if (info==NULL) {
6724                 *returned=0;
6725                 return WERR_NOMEM;
6726         }
6727
6728         for (i=0; i<*returned; i++)
6729                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6730
6731         /* check the required size. */
6732         for (i=0; i<*returned; i++)
6733                 (*needed) += spoolss_size_job_info_1(&info[i]);
6734
6735         if (*needed > offered) {
6736                 result = WERR_INSUFFICIENT_BUFFER;
6737                 goto out;
6738         }
6739
6740         if (!rpcbuf_alloc_size(buffer, *needed)) {
6741                 result = WERR_NOMEM;
6742                 goto out;
6743         }
6744
6745         /* fill the buffer with the structures */
6746         for (i=0; i<*returned; i++)
6747                 smb_io_job_info_1("", buffer, &info[i], 0);
6748
6749 out:
6750         /* clear memory */
6751         SAFE_FREE(info);
6752
6753         if ( !W_ERROR_IS_OK(result) )
6754                 *returned = 0;
6755
6756         return result;
6757 }
6758
6759 /****************************************************************************
6760  Enumjobs at level 2.
6761 ****************************************************************************/
6762
6763 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6764                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6765                               RPC_BUFFER *buffer, uint32 offered,
6766                               uint32 *needed, uint32 *returned)
6767 {
6768         JOB_INFO_2 *info = NULL;
6769         int i;
6770         WERROR result = WERR_OK;
6771         DEVICEMODE *devmode = NULL;
6772
6773         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6774                 *returned=0;
6775                 return WERR_NOMEM;
6776         }
6777
6778         /* this should not be a failure condition if the devmode is NULL */
6779
6780         devmode = construct_dev_mode(lp_const_servicename(snum));
6781
6782         for (i=0; i<*returned; i++)
6783                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6784
6785         /* check the required size. */
6786         for (i=0; i<*returned; i++)
6787                 (*needed) += spoolss_size_job_info_2(&info[i]);
6788
6789         if (*needed > offered) {
6790                 result = WERR_INSUFFICIENT_BUFFER;
6791                 goto out;
6792         }
6793
6794         if (!rpcbuf_alloc_size(buffer, *needed)) {
6795                 result = WERR_NOMEM;
6796                 goto out;
6797         }
6798
6799         /* fill the buffer with the structures */
6800         for (i=0; i<*returned; i++)
6801                 smb_io_job_info_2("", buffer, &info[i], 0);
6802
6803 out:
6804         free_devmode(devmode);
6805         SAFE_FREE(info);
6806
6807         if ( !W_ERROR_IS_OK(result) )
6808                 *returned = 0;
6809
6810         return result;
6811
6812 }
6813
6814 /****************************************************************************
6815  Enumjobs.
6816 ****************************************************************************/
6817
6818 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6819 {
6820         POLICY_HND *handle = &q_u->handle;
6821         uint32 level = q_u->level;
6822         RPC_BUFFER *buffer = NULL;
6823         uint32 offered = q_u->offered;
6824         uint32 *needed = &r_u->needed;
6825         uint32 *returned = &r_u->returned;
6826         WERROR wret;
6827         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6828         int snum;
6829         print_status_struct prt_status;
6830         print_queue_struct *queue=NULL;
6831
6832         /* that's an [in out] buffer */
6833
6834         if (!q_u->buffer && (offered!=0)) {
6835                 return WERR_INVALID_PARAM;
6836         }
6837
6838         if (offered > MAX_RPC_DATA_SIZE) {
6839                 return WERR_INVALID_PARAM;
6840         }
6841
6842         rpcbuf_move(q_u->buffer, &r_u->buffer);
6843         buffer = r_u->buffer;
6844
6845         DEBUG(4,("_spoolss_enumjobs\n"));
6846
6847         *needed=0;
6848         *returned=0;
6849
6850         /* lookup the printer snum and tdb entry */
6851
6852         if (!get_printer_snum(p, handle, &snum, NULL))
6853                 return WERR_BADFID;
6854
6855         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6856         if ( !W_ERROR_IS_OK(wret) )
6857                 return wret;
6858
6859         *returned = print_queue_status(snum, &queue, &prt_status);
6860         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6861
6862         if (*returned == 0) {
6863                 SAFE_FREE(queue);
6864                 free_a_printer(&ntprinter, 2);
6865                 return WERR_OK;
6866         }
6867
6868         switch (level) {
6869         case 1:
6870                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6871                 break;
6872         case 2:
6873                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6874                 break;
6875         default:
6876                 *returned=0;
6877                 wret = WERR_UNKNOWN_LEVEL;
6878                 break;
6879         }
6880
6881         SAFE_FREE(queue);
6882         free_a_printer( &ntprinter, 2 );
6883         return wret;
6884 }
6885
6886 /****************************************************************
6887  _spoolss_ScheduleJob
6888 ****************************************************************/
6889
6890 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6891                             struct spoolss_ScheduleJob *r)
6892 {
6893         return WERR_OK;
6894 }
6895
6896 /****************************************************************
6897  _spoolss_SetJob
6898 ****************************************************************/
6899
6900 WERROR _spoolss_SetJob(pipes_struct *p,
6901                        struct spoolss_SetJob *r)
6902 {
6903         POLICY_HND *handle = r->in.handle;
6904         uint32 jobid = r->in.job_id;
6905         uint32 command = r->in.command;
6906
6907         int snum;
6908         WERROR errcode = WERR_BADFUNC;
6909
6910         if (!get_printer_snum(p, handle, &snum, NULL)) {
6911                 return WERR_BADFID;
6912         }
6913
6914         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6915                 return WERR_INVALID_PRINTER_NAME;
6916         }
6917
6918         switch (command) {
6919         case SPOOLSS_JOB_CONTROL_CANCEL:
6920         case SPOOLSS_JOB_CONTROL_DELETE:
6921                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6922                         errcode = WERR_OK;
6923                 }
6924                 break;
6925         case SPOOLSS_JOB_CONTROL_PAUSE:
6926                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6927                         errcode = WERR_OK;
6928                 }
6929                 break;
6930         case SPOOLSS_JOB_CONTROL_RESTART:
6931         case SPOOLSS_JOB_CONTROL_RESUME:
6932                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6933                         errcode = WERR_OK;
6934                 }
6935                 break;
6936         default:
6937                 return WERR_UNKNOWN_LEVEL;
6938         }
6939
6940         return errcode;
6941 }
6942
6943 /****************************************************************************
6944  Enumerates all printer drivers at level 1.
6945 ****************************************************************************/
6946
6947 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6948 {
6949         int i;
6950         int ndrivers;
6951         uint32 version;
6952         fstring *list = NULL;
6953         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6954         DRIVER_INFO_1 *driver_info_1=NULL;
6955         WERROR result = WERR_OK;
6956
6957         *returned=0;
6958
6959         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6960                 list=NULL;
6961                 ndrivers=get_ntdrivers(&list, architecture, version);
6962                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6963
6964                 if(ndrivers == -1) {
6965                         SAFE_FREE(driver_info_1);
6966                         return WERR_NOMEM;
6967                 }
6968
6969                 if(ndrivers != 0) {
6970                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6971                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6972                                 SAFE_FREE(list);
6973                                 return WERR_NOMEM;
6974                         }
6975                 }
6976
6977                 for (i=0; i<ndrivers; i++) {
6978                         WERROR status;
6979                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6980                         ZERO_STRUCT(driver);
6981                         status = get_a_printer_driver(&driver, 3, list[i],
6982                                                       architecture, version);
6983                         if (!W_ERROR_IS_OK(status)) {
6984                                 SAFE_FREE(list);
6985                                 SAFE_FREE(driver_info_1);
6986                                 return status;
6987                         }
6988                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6989                         free_a_printer_driver(driver, 3);
6990                 }
6991
6992                 *returned+=ndrivers;
6993                 SAFE_FREE(list);
6994         }
6995
6996         /* check the required size. */
6997         for (i=0; i<*returned; i++) {
6998                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6999                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
7000         }
7001
7002         if (*needed > offered) {
7003                 result = WERR_INSUFFICIENT_BUFFER;
7004                 goto out;
7005         }
7006
7007         if (!rpcbuf_alloc_size(buffer, *needed)) {
7008                 result = WERR_NOMEM;
7009                 goto out;
7010         }
7011
7012         /* fill the buffer with the driver structures */
7013         for (i=0; i<*returned; i++) {
7014                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7015                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7016         }
7017
7018 out:
7019         SAFE_FREE(driver_info_1);
7020
7021         if ( !W_ERROR_IS_OK(result) )
7022                 *returned = 0;
7023
7024         return result;
7025 }
7026
7027 /****************************************************************************
7028  Enumerates all printer drivers at level 2.
7029 ****************************************************************************/
7030
7031 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7032 {
7033         int i;
7034         int ndrivers;
7035         uint32 version;
7036         fstring *list = NULL;
7037         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7038         DRIVER_INFO_2 *driver_info_2=NULL;
7039         WERROR result = WERR_OK;
7040
7041         *returned=0;
7042
7043         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7044                 list=NULL;
7045                 ndrivers=get_ntdrivers(&list, architecture, version);
7046                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7047
7048                 if(ndrivers == -1) {
7049                         SAFE_FREE(driver_info_2);
7050                         return WERR_NOMEM;
7051                 }
7052
7053                 if(ndrivers != 0) {
7054                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7055                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7056                                 SAFE_FREE(list);
7057                                 return WERR_NOMEM;
7058                         }
7059                 }
7060
7061                 for (i=0; i<ndrivers; i++) {
7062                         WERROR status;
7063
7064                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7065                         ZERO_STRUCT(driver);
7066                         status = get_a_printer_driver(&driver, 3, list[i],
7067                                                       architecture, version);
7068                         if (!W_ERROR_IS_OK(status)) {
7069                                 SAFE_FREE(list);
7070                                 SAFE_FREE(driver_info_2);
7071                                 return status;
7072                         }
7073                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7074                         free_a_printer_driver(driver, 3);
7075                 }
7076
7077                 *returned+=ndrivers;
7078                 SAFE_FREE(list);
7079         }
7080
7081         /* check the required size. */
7082         for (i=0; i<*returned; i++) {
7083                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7084                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7085         }
7086
7087         if (*needed > offered) {
7088                 result = WERR_INSUFFICIENT_BUFFER;
7089                 goto out;
7090         }
7091
7092         if (!rpcbuf_alloc_size(buffer, *needed)) {
7093                 result = WERR_NOMEM;
7094                 goto out;
7095         }
7096
7097         /* fill the buffer with the form structures */
7098         for (i=0; i<*returned; i++) {
7099                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7100                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7101         }
7102
7103 out:
7104         SAFE_FREE(driver_info_2);
7105
7106         if ( !W_ERROR_IS_OK(result) )
7107                 *returned = 0;
7108
7109         return result;
7110 }
7111
7112 /****************************************************************************
7113  Enumerates all printer drivers at level 3.
7114 ****************************************************************************/
7115
7116 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7117 {
7118         int i;
7119         int ndrivers;
7120         uint32 version;
7121         fstring *list = NULL;
7122         DRIVER_INFO_3 *driver_info_3=NULL;
7123         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7124         WERROR result = WERR_OK;
7125
7126         *returned=0;
7127
7128         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7129                 list=NULL;
7130                 ndrivers=get_ntdrivers(&list, architecture, version);
7131                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7132
7133                 if(ndrivers == -1) {
7134                         SAFE_FREE(driver_info_3);
7135                         return WERR_NOMEM;
7136                 }
7137
7138                 if(ndrivers != 0) {
7139                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7140                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7141                                 SAFE_FREE(list);
7142                                 return WERR_NOMEM;
7143                         }
7144                 }
7145
7146                 for (i=0; i<ndrivers; i++) {
7147                         WERROR status;
7148
7149                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7150                         ZERO_STRUCT(driver);
7151                         status = get_a_printer_driver(&driver, 3, list[i],
7152                                                       architecture, version);
7153                         if (!W_ERROR_IS_OK(status)) {
7154                                 SAFE_FREE(list);
7155                                 SAFE_FREE(driver_info_3);
7156                                 return status;
7157                         }
7158                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7159                         free_a_printer_driver(driver, 3);
7160                 }
7161
7162                 *returned+=ndrivers;
7163                 SAFE_FREE(list);
7164         }
7165
7166         /* check the required size. */
7167         for (i=0; i<*returned; i++) {
7168                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7169                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7170         }
7171
7172         if (*needed > offered) {
7173                 result = WERR_INSUFFICIENT_BUFFER;
7174                 goto out;
7175         }
7176
7177         if (!rpcbuf_alloc_size(buffer, *needed)) {
7178                 result = WERR_NOMEM;
7179                 goto out;
7180         }
7181
7182         /* fill the buffer with the driver structures */
7183         for (i=0; i<*returned; i++) {
7184                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7185                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7186         }
7187
7188 out:
7189         for (i=0; i<*returned; i++) {
7190                 SAFE_FREE(driver_info_3[i].dependentfiles);
7191         }
7192
7193         SAFE_FREE(driver_info_3);
7194
7195         if ( !W_ERROR_IS_OK(result) )
7196                 *returned = 0;
7197
7198         return result;
7199 }
7200
7201 /****************************************************************************
7202  Enumerates all printer drivers.
7203 ****************************************************************************/
7204
7205 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7206 {
7207         uint32 level = q_u->level;
7208         RPC_BUFFER *buffer = NULL;
7209         uint32 offered = q_u->offered;
7210         uint32 *needed = &r_u->needed;
7211         uint32 *returned = &r_u->returned;
7212         const char *cservername;
7213         fstring servername;
7214         fstring architecture;
7215
7216         /* that's an [in out] buffer */
7217
7218         if (!q_u->buffer && (offered!=0)) {
7219                 return WERR_INVALID_PARAM;
7220         }
7221
7222         if (offered > MAX_RPC_DATA_SIZE) {
7223                 return WERR_INVALID_PARAM;
7224         }
7225
7226         rpcbuf_move(q_u->buffer, &r_u->buffer);
7227         buffer = r_u->buffer;
7228
7229         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7230
7231         *needed   = 0;
7232         *returned = 0;
7233
7234         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7235         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7236
7237         cservername = canon_servername(servername);
7238
7239         if (!is_myname_or_ipaddr(cservername))
7240                 return WERR_UNKNOWN_PRINTER_DRIVER;
7241
7242         switch (level) {
7243         case 1:
7244                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7245         case 2:
7246                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7247         case 3:
7248                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7249         default:
7250                 return WERR_UNKNOWN_LEVEL;
7251         }
7252 }
7253
7254 /****************************************************************************
7255 ****************************************************************************/
7256
7257 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7258                                struct spoolss_FormInfo1 *form,
7259                                nt_forms_struct *list)
7260 {
7261         form->form_name         = talloc_strdup(mem_ctx, list->name);
7262         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7263
7264         form->flags             = list->flag;
7265         form->size.width        = list->width;
7266         form->size.height       = list->length;
7267         form->area.left         = list->left;
7268         form->area.top          = list->top;
7269         form->area.right        = list->right;
7270         form->area.bottom       = list->bottom;
7271
7272         return WERR_OK;
7273 }
7274
7275 /****************************************************************
7276  _spoolss_EnumForms
7277 ****************************************************************/
7278
7279 WERROR _spoolss_EnumForms(pipes_struct *p,
7280                           struct spoolss_EnumForms *r)
7281 {
7282         nt_forms_struct *list=NULL;
7283         nt_forms_struct *builtinlist=NULL;
7284         union spoolss_FormInfo *info;
7285         uint32_t count;
7286         uint32_t numbuiltinforms;
7287         size_t buffer_size = 0;
7288         int i;
7289
7290         *r->out.count = 0;
7291
7292         /* that's an [in out] buffer */
7293
7294         if (!r->in.buffer && (r->in.offered != 0) ) {
7295                 return WERR_INVALID_PARAM;
7296         }
7297
7298         DEBUG(4,("_spoolss_EnumForms\n"));
7299         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7300         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7301
7302         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7303         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7304         count = get_ntforms(&list);
7305         DEBUGADD(5,("Number of user forms [%d]\n",     count));
7306         count += numbuiltinforms;
7307
7308         if (count == 0) {
7309                 SAFE_FREE(builtinlist);
7310                 SAFE_FREE(list);
7311                 return WERR_NO_MORE_ITEMS;
7312         }
7313
7314         info = TALLOC_ARRAY(p->mem_ctx, union spoolss_FormInfo, count);
7315         if (!info) {
7316                 SAFE_FREE(builtinlist);
7317                 SAFE_FREE(list);
7318                 return WERR_NOMEM;
7319         }
7320
7321         switch (r->in.level) {
7322         case 1:
7323                 /* construct the list of form structures */
7324                 for (i=0; i<numbuiltinforms; i++) {
7325                         DEBUGADD(6,("Filling form number [%d]\n",i));
7326                         fill_form_info_1(info, &info[i].info1, &builtinlist[i]);
7327                 }
7328
7329                 SAFE_FREE(builtinlist);
7330
7331                 for (; i<count; i++) {
7332                         DEBUGADD(6,("Filling form number [%d]\n",i));
7333                         fill_form_info_1(info, &info[i].info1, &list[i-numbuiltinforms]);
7334                 }
7335
7336                 SAFE_FREE(list);
7337
7338                 /* check the required size. */
7339                 for (i=0; i<numbuiltinforms; i++) {
7340                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7341                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7342                 }
7343                 for (; i<count; i++) {
7344                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7345                         buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7346                 }
7347
7348                 *r->out.needed = buffer_size;
7349
7350                 if (*r->out.needed > r->in.offered) {
7351                         TALLOC_FREE(info);
7352                         return WERR_INSUFFICIENT_BUFFER;
7353                 }
7354
7355                 *r->out.count = count;
7356                 *r->out.info = info;
7357
7358                 return WERR_OK;
7359
7360         default:
7361                 SAFE_FREE(list);
7362                 SAFE_FREE(builtinlist);
7363                 return WERR_UNKNOWN_LEVEL;
7364         }
7365 }
7366
7367 /****************************************************************
7368  _spoolss_GetForm
7369 ****************************************************************/
7370
7371 WERROR _spoolss_GetForm(pipes_struct *p,
7372                         struct spoolss_GetForm *r)
7373 {
7374         uint32 level = r->in.level;
7375         uint32 offered = r->in.offered;
7376         uint32 *needed = r->out.needed;
7377
7378         nt_forms_struct *list=NULL;
7379         nt_forms_struct builtin_form;
7380         bool foundBuiltin;
7381         union spoolss_FormInfo info;
7382         struct spoolss_FormInfo1 form_1;
7383         int numofforms=0, i=0;
7384
7385         /* that's an [in out] buffer */
7386
7387         if (!r->in.buffer && (offered!=0)) {
7388                 return WERR_INVALID_PARAM;
7389         }
7390
7391         DEBUG(4,("_spoolss_GetForm\n"));
7392         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7393         DEBUGADD(5,("Info level [%d]\n",          level));
7394
7395         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7396         if (!foundBuiltin) {
7397                 numofforms = get_ntforms(&list);
7398                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7399
7400                 if (numofforms == 0)
7401                         return WERR_BADFID;
7402         }
7403
7404         ZERO_STRUCT(form_1);
7405
7406         switch (level) {
7407         case 1:
7408                 if (foundBuiltin) {
7409                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7410                 } else {
7411
7412                         /* Check if the requested name is in the list of form structures */
7413                         for (i=0; i<numofforms; i++) {
7414
7415                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7416                                         list[i].name, r->in.form_name));
7417
7418                                 if (strequal(r->in.form_name, list[i].name)) {
7419                                         DEBUGADD(6,("Found form %s number [%d]\n",
7420                                                 r->in.form_name, i));
7421                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7422                                         break;
7423                                 }
7424                         }
7425
7426                         SAFE_FREE(list);
7427                         if (i == numofforms) {
7428                                 return WERR_BADFID;
7429                         }
7430                 }
7431                 /* check the required size. */
7432
7433                 info.info1 = form_1;
7434
7435                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7436
7437                 if (*needed > offered) {
7438                         r->out.info = NULL;
7439                         return WERR_INSUFFICIENT_BUFFER;
7440                 }
7441
7442                 r->out.info->info1 = form_1;
7443
7444                 /* fill the buffer with the form structures */
7445                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7446                         r->in.form_name, i));
7447
7448                 return WERR_OK;
7449
7450         default:
7451                 SAFE_FREE(list);
7452                 return WERR_UNKNOWN_LEVEL;
7453         }
7454 }
7455
7456 /****************************************************************************
7457 ****************************************************************************/
7458
7459 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7460                           struct spoolss_PortInfo1 *r,
7461                           const char *name)
7462 {
7463         r->port_name = talloc_strdup(mem_ctx, name);
7464         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7465
7466         return WERR_OK;
7467 }
7468
7469 /****************************************************************************
7470  TODO: This probably needs distinguish between TCP/IP and Local ports
7471  somehow.
7472 ****************************************************************************/
7473
7474 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7475                           struct spoolss_PortInfo2 *r,
7476                           const char *name)
7477 {
7478         r->port_name = talloc_strdup(mem_ctx, name);
7479         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7480
7481         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7482         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7483
7484         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7485         W_ERROR_HAVE_NO_MEMORY(r->description);
7486
7487         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7488         r->reserved = 0;
7489
7490         return WERR_OK;
7491 }
7492
7493
7494 /****************************************************************************
7495  wrapper around the enumer ports command
7496 ****************************************************************************/
7497
7498 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7499 {
7500         char *cmd = lp_enumports_cmd();
7501         char **qlines = NULL;
7502         char *command = NULL;
7503         int numlines;
7504         int ret;
7505         int fd;
7506
7507         *count = 0;
7508         *lines = NULL;
7509
7510         /* if no hook then just fill in the default port */
7511
7512         if ( !*cmd ) {
7513                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7514                         return WERR_NOMEM;
7515                 }
7516                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7517                         TALLOC_FREE(qlines);
7518                         return WERR_NOMEM;
7519                 }
7520                 qlines[1] = NULL;
7521                 numlines = 1;
7522         }
7523         else {
7524                 /* we have a valid enumport command */
7525
7526                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7527                 if (!command) {
7528                         return WERR_NOMEM;
7529                 }
7530
7531                 DEBUG(10,("Running [%s]\n", command));
7532                 ret = smbrun(command, &fd);
7533                 DEBUG(10,("Returned [%d]\n", ret));
7534                 TALLOC_FREE(command);
7535                 if (ret != 0) {
7536                         if (fd != -1) {
7537                                 close(fd);
7538                         }
7539                         return WERR_ACCESS_DENIED;
7540                 }
7541
7542                 numlines = 0;
7543                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7544                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7545                 close(fd);
7546         }
7547
7548         *count = numlines;
7549         *lines = qlines;
7550
7551         return WERR_OK;
7552 }
7553
7554 /****************************************************************************
7555  enumports level 1.
7556 ****************************************************************************/
7557
7558 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7559                                 union spoolss_PortInfo **info_p,
7560                                 uint32_t *count)
7561 {
7562         union spoolss_PortInfo *info = NULL;
7563         int i=0;
7564         WERROR result = WERR_OK;
7565         char **qlines = NULL;
7566         int numlines = 0;
7567
7568         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7569         if (!W_ERROR_IS_OK(result)) {
7570                 goto out;
7571         }
7572
7573         if (numlines) {
7574                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7575                 if (!info) {
7576                         DEBUG(10,("Returning WERR_NOMEM\n"));
7577                         result = WERR_NOMEM;
7578                         goto out;
7579                 }
7580
7581                 for (i=0; i<numlines; i++) {
7582                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7583                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7584                         if (!W_ERROR_IS_OK(result)) {
7585                                 goto out;
7586                         }
7587                 }
7588         }
7589         TALLOC_FREE(qlines);
7590
7591 out:
7592         if (!W_ERROR_IS_OK(result)) {
7593                 TALLOC_FREE(info);
7594                 TALLOC_FREE(qlines);
7595                 *count = 0;
7596                 *info_p = NULL;
7597                 return result;
7598         }
7599
7600         *info_p = info;
7601         *count = numlines;
7602
7603         return WERR_OK;
7604 }
7605
7606 /****************************************************************************
7607  enumports level 2.
7608 ****************************************************************************/
7609
7610 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7611                                 union spoolss_PortInfo **info_p,
7612                                 uint32_t *count)
7613 {
7614         union spoolss_PortInfo *info = NULL;
7615         int i=0;
7616         WERROR result = WERR_OK;
7617         char **qlines = NULL;
7618         int numlines = 0;
7619
7620         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7621         if (!W_ERROR_IS_OK(result)) {
7622                 goto out;
7623         }
7624
7625         if (numlines) {
7626                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7627                 if (!info) {
7628                         DEBUG(10,("Returning WERR_NOMEM\n"));
7629                         result = WERR_NOMEM;
7630                         goto out;
7631                 }
7632
7633                 for (i=0; i<numlines; i++) {
7634                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7635                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7636                         if (!W_ERROR_IS_OK(result)) {
7637                                 goto out;
7638                         }
7639                 }
7640         }
7641         TALLOC_FREE(qlines);
7642
7643 out:
7644         if (!W_ERROR_IS_OK(result)) {
7645                 TALLOC_FREE(info);
7646                 TALLOC_FREE(qlines);
7647                 *count = 0;
7648                 *info_p = NULL;
7649                 return result;
7650         }
7651
7652         *info_p = info;
7653         *count = numlines;
7654
7655         return WERR_OK;
7656 }
7657
7658 /****************************************************************
7659  _spoolss_EnumPorts
7660 ****************************************************************/
7661
7662 WERROR _spoolss_EnumPorts(pipes_struct *p,
7663                           struct spoolss_EnumPorts *r)
7664 {
7665         WERROR result;
7666
7667         /* that's an [in out] buffer */
7668
7669         if (!r->in.buffer && (r->in.offered != 0)) {
7670                 return WERR_INVALID_PARAM;
7671         }
7672
7673         DEBUG(4,("_spoolss_EnumPorts\n"));
7674
7675         *r->out.count = 0;
7676         *r->out.needed = 0;
7677         *r->out.info = NULL;
7678
7679         switch (r->in.level) {
7680         case 1:
7681                 result = enumports_level_1(p->mem_ctx, r->out.info,
7682                                            r->out.count);
7683                 break;
7684         case 2:
7685                 result = enumports_level_2(p->mem_ctx, r->out.info,
7686                                            r->out.count);
7687                 break;
7688         default:
7689                 return WERR_UNKNOWN_LEVEL;
7690         }
7691
7692         if (!W_ERROR_IS_OK(result)) {
7693                 return result;
7694         }
7695
7696         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7697                                                      spoolss_EnumPorts, NULL,
7698                                                      *r->out.info, r->in.level,
7699                                                      *r->out.count);
7700         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7701         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7702
7703         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7704 }
7705
7706 /****************************************************************************
7707 ****************************************************************************/
7708
7709 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7710                                            const char *server,
7711                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7712                                            struct spoolss_DeviceMode *devmode,
7713                                            struct security_descriptor *sec_desc,
7714                                            struct spoolss_UserLevelCtr *user_ctr,
7715                                            POLICY_HND *handle)
7716 {
7717         NT_PRINTER_INFO_LEVEL *printer = NULL;
7718         fstring name;
7719         int     snum;
7720         WERROR err = WERR_OK;
7721
7722         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7723                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7724                 return WERR_NOMEM;
7725         }
7726
7727         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7728         if (!convert_printer_info_new(info_ctr, printer)) {
7729                 free_a_printer(&printer, 2);
7730                 return WERR_NOMEM;
7731         }
7732
7733         /* check to see if the printer already exists */
7734
7735         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7736                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7737                         printer->info_2->sharename));
7738                 free_a_printer(&printer, 2);
7739                 return WERR_PRINTER_ALREADY_EXISTS;
7740         }
7741
7742         /* FIXME!!!  smbd should check to see if the driver is installed before
7743            trying to add a printer like this  --jerry */
7744
7745         if (*lp_addprinter_cmd() ) {
7746                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7747                                        printer) ) {
7748                         free_a_printer(&printer,2);
7749                         return WERR_ACCESS_DENIED;
7750                 }
7751         } else {
7752                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7753                         "smb.conf parameter \"addprinter command\" is defined. This"
7754                         "parameter must exist for this call to succeed\n",
7755                         printer->info_2->sharename ));
7756         }
7757
7758         /* use our primary netbios name since get_a_printer() will convert
7759            it to what the client expects on a case by case basis */
7760
7761         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7762              printer->info_2->sharename);
7763
7764
7765         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7766                 free_a_printer(&printer,2);
7767                 return WERR_ACCESS_DENIED;
7768         }
7769
7770         /* you must be a printer admin to add a new printer */
7771         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7772                 free_a_printer(&printer,2);
7773                 return WERR_ACCESS_DENIED;
7774         }
7775
7776         /*
7777          * Do sanity check on the requested changes for Samba.
7778          */
7779
7780         if (!check_printer_ok(printer->info_2, snum)) {
7781                 free_a_printer(&printer,2);
7782                 return WERR_INVALID_PARAM;
7783         }
7784
7785         /*
7786          * When a printer is created, the drivername bound to the printer is used
7787          * to lookup previously saved driver initialization info, which is then
7788          * bound to the new printer, simulating what happens in the Windows arch.
7789          */
7790
7791         if (!devmode)
7792         {
7793                 set_driver_init(printer, 2);
7794         }
7795         else
7796         {
7797                 /* A valid devmode was included, convert and link it
7798                 */
7799                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7800
7801                 if (!convert_devicemode_new(printer->info_2->printername,
7802                                             devmode,
7803                                             &printer->info_2->devmode))
7804                         return  WERR_NOMEM;
7805         }
7806
7807         /* write the ASCII on disk */
7808         err = mod_a_printer(printer, 2);
7809         if (!W_ERROR_IS_OK(err)) {
7810                 free_a_printer(&printer,2);
7811                 return err;
7812         }
7813
7814         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7815                 /* Handle open failed - remove addition. */
7816                 del_a_printer(printer->info_2->sharename);
7817                 free_a_printer(&printer,2);
7818                 ZERO_STRUCTP(handle);
7819                 return WERR_ACCESS_DENIED;
7820         }
7821
7822         update_c_setprinter(False);
7823         free_a_printer(&printer,2);
7824
7825         return WERR_OK;
7826 }
7827
7828 /****************************************************************
7829  _spoolss_AddPrinterEx
7830 ****************************************************************/
7831
7832 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7833                              struct spoolss_AddPrinterEx *r)
7834 {
7835         switch (r->in.info_ctr->level) {
7836         case 1:
7837                 /* we don't handle yet */
7838                 /* but I know what to do ... */
7839                 return WERR_UNKNOWN_LEVEL;
7840         case 2:
7841                 return spoolss_addprinterex_level_2(p, r->in.server,
7842                                                     r->in.info_ctr,
7843                                                     r->in.devmode_ctr->devmode,
7844                                                     r->in.secdesc_ctr->sd,
7845                                                     r->in.userlevel_ctr,
7846                                                     r->out.handle);
7847         default:
7848                 return WERR_UNKNOWN_LEVEL;
7849         }
7850 }
7851
7852 /****************************************************************
7853  _spoolss_AddPrinterDriver
7854 ****************************************************************/
7855
7856 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7857                                  struct spoolss_AddPrinterDriver *r)
7858 {
7859         uint32_t level = r->in.info_ctr->level;
7860         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7861         WERROR err = WERR_OK;
7862         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7863         fstring driver_name;
7864         uint32 version;
7865         const char *fn;
7866
7867         switch (p->hdr_req.opnum) {
7868                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7869                         fn = "_spoolss_AddPrinterDriver";
7870                         break;
7871                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7872                         fn = "_spoolss_AddPrinterDriverEx";
7873                         break;
7874                 default:
7875                         return WERR_INVALID_PARAM;
7876         }
7877
7878
7879         /* FIXME */
7880         if (level != 3 && level != 6) {
7881                 /* Clever hack from Martin Zielinski <mz@seh.de>
7882                  * to allow downgrade from level 8 (Vista).
7883                  */
7884                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7885                 return WERR_UNKNOWN_LEVEL;
7886         }
7887
7888         ZERO_STRUCT(driver);
7889
7890         if (!convert_printer_driver_info(info, &driver, level)) {
7891                 err = WERR_NOMEM;
7892                 goto done;
7893         }
7894
7895         DEBUG(5,("Cleaning driver's information\n"));
7896         err = clean_up_driver_struct(p, driver, level);
7897         if (!W_ERROR_IS_OK(err))
7898                 goto done;
7899
7900         DEBUG(5,("Moving driver to final destination\n"));
7901         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7902                                                               &err)) ) {
7903                 goto done;
7904         }
7905
7906         if (add_a_printer_driver(driver, level)!=0) {
7907                 err = WERR_ACCESS_DENIED;
7908                 goto done;
7909         }
7910
7911         switch(level) {
7912         case 3:
7913                 fstrcpy(driver_name,
7914                         driver.info_3->name ? driver.info_3->name : "");
7915                 break;
7916         case 6:
7917                 fstrcpy(driver_name,
7918                         driver.info_6->name ?  driver.info_6->name : "");
7919                 break;
7920         }
7921
7922         /*
7923          * I think this is where he DrvUpgradePrinter() hook would be
7924          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7925          * server.  Right now, we just need to send ourselves a message
7926          * to update each printer bound to this driver.   --jerry
7927          */
7928
7929         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7930                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7931                         fn, driver_name));
7932         }
7933
7934         /*
7935          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7936          * decide if the driver init data should be deleted. The rules are:
7937          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7938          *  2) delete init data only if there is no 2k/Xp driver
7939          *  3) always delete init data
7940          * The generalized rule is always use init data from the highest order driver.
7941          * It is necessary to follow the driver install by an initialization step to
7942          * finish off this process.
7943         */
7944         if (level == 3)
7945                 version = driver.info_3->cversion;
7946         else if (level == 6)
7947                 version = driver.info_6->version;
7948         else
7949                 version = -1;
7950         switch (version) {
7951                 /*
7952                  * 9x printer driver - never delete init data
7953                 */
7954                 case 0:
7955                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7956                                 fn, driver_name));
7957                         break;
7958
7959                 /*
7960                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7961                  * there is no 2k/Xp driver init data for this driver name.
7962                 */
7963                 case 2:
7964                 {
7965                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7966
7967                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7968                                 /*
7969                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7970                                 */
7971                                 if (!del_driver_init(driver_name))
7972                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7973                                                 fn, driver_name));
7974                         } else {
7975                                 /*
7976                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7977                                 */
7978                                 free_a_printer_driver(driver1,3);
7979                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7980                                         fn, driver_name));
7981                         }
7982                 }
7983                 break;
7984
7985                 /*
7986                  * 2k or Xp printer driver - always delete init data
7987                 */
7988                 case 3:
7989                         if (!del_driver_init(driver_name))
7990                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7991                                         fn, driver_name));
7992                         break;
7993
7994                 default:
7995                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7996                         break;
7997         }
7998
7999
8000 done:
8001         free_a_printer_driver(driver, level);
8002         return err;
8003 }
8004
8005 /****************************************************************
8006  _spoolss_AddPrinterDriverEx
8007 ****************************************************************/
8008
8009 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8010                                    struct spoolss_AddPrinterDriverEx *r)
8011 {
8012         struct spoolss_AddPrinterDriver a;
8013
8014         /*
8015          * we only support the semantics of AddPrinterDriver()
8016          * i.e. only copy files that are newer than existing ones
8017          */
8018
8019         if (r->in.flags != APD_COPY_NEW_FILES) {
8020                 return WERR_ACCESS_DENIED;
8021         }
8022
8023         a.in.servername         = r->in.servername;
8024         a.in.info_ctr           = r->in.info_ctr;
8025
8026         return _spoolss_AddPrinterDriver(p, &a);
8027 }
8028
8029 /****************************************************************************
8030 ****************************************************************************/
8031
8032 struct _spoolss_paths {
8033         int type;
8034         const char *share;
8035         const char *dir;
8036 };
8037
8038 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8039
8040 static const struct _spoolss_paths spoolss_paths[]= {
8041         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8042         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8043 };
8044
8045 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8046                                           const char *servername,
8047                                           const char *environment,
8048                                           int component,
8049                                           char **path)
8050 {
8051         const char *pservername = NULL;
8052         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8053         const char *short_archi;
8054
8055         *path = NULL;
8056
8057         /* environment may be empty */
8058         if (environment && strlen(environment)) {
8059                 long_archi = environment;
8060         }
8061
8062         /* servername may be empty */
8063         if (servername && strlen(servername)) {
8064                 pservername = canon_servername(servername);
8065
8066                 if (!is_myname_or_ipaddr(pservername)) {
8067                         return WERR_INVALID_PARAM;
8068                 }
8069         }
8070
8071         if (!(short_archi = get_short_archi(long_archi))) {
8072                 return WERR_INVALID_ENVIRONMENT;
8073         }
8074
8075         switch (component) {
8076         case SPOOLSS_PRTPROCS_PATH:
8077         case SPOOLSS_DRIVER_PATH:
8078                 if (pservername) {
8079                         *path = talloc_asprintf(mem_ctx,
8080                                         "\\\\%s\\%s\\%s",
8081                                         pservername,
8082                                         spoolss_paths[component].share,
8083                                         short_archi);
8084                 } else {
8085                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8086                                         SPOOLSS_DEFAULT_SERVER_PATH,
8087                                         spoolss_paths[component].dir,
8088                                         short_archi);
8089                 }
8090                 break;
8091         default:
8092                 return WERR_INVALID_PARAM;
8093         }
8094
8095         if (!*path) {
8096                 return WERR_NOMEM;
8097         }
8098
8099         return WERR_OK;
8100 }
8101
8102 /****************************************************************************
8103 ****************************************************************************/
8104
8105 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8106                                           const char *servername,
8107                                           const char *environment,
8108                                           struct spoolss_DriverDirectoryInfo1 *r,
8109                                           uint32_t offered,
8110                                           uint32_t *needed)
8111 {
8112         WERROR werr;
8113         char *path = NULL;
8114
8115         werr = compose_spoolss_server_path(mem_ctx,
8116                                            servername,
8117                                            environment,
8118                                            SPOOLSS_DRIVER_PATH,
8119                                            &path);
8120         if (!W_ERROR_IS_OK(werr)) {
8121                 return werr;
8122         }
8123
8124         DEBUG(4,("printer driver directory: [%s]\n", path));
8125
8126         r->directory_name = path;
8127
8128         *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8129
8130         if (*needed > offered) {
8131                 talloc_free(path);
8132                 return WERR_INSUFFICIENT_BUFFER;
8133         }
8134
8135         return WERR_OK;
8136 }
8137
8138 /****************************************************************
8139  _spoolss_GetPrinterDriverDirectory
8140 ****************************************************************/
8141
8142 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8143                                           struct spoolss_GetPrinterDriverDirectory *r)
8144 {
8145         WERROR werror;
8146
8147         /* that's an [in out] buffer */
8148
8149         if (!r->in.buffer && (r->in.offered != 0)) {
8150                 return WERR_INVALID_PARAM;
8151         }
8152
8153         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8154                 r->in.level));
8155
8156         *r->out.needed = 0;
8157
8158         /* r->in.level is ignored */
8159
8160         werror = getprinterdriverdir_level_1(p->mem_ctx,
8161                                              r->in.server,
8162                                              r->in.environment,
8163                                              &r->out.info->info1,
8164                                              r->in.offered,
8165                                              r->out.needed);
8166         if (!W_ERROR_IS_OK(werror)) {
8167                 TALLOC_FREE(r->out.info);
8168         }
8169
8170         return werror;
8171 }
8172
8173 /****************************************************************************
8174 ****************************************************************************/
8175
8176 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8177 {
8178         POLICY_HND *handle = &q_u->handle;
8179         uint32 idx               = q_u->index;
8180         uint32 in_value_len      = q_u->valuesize;
8181         uint32 in_data_len       = q_u->datasize;
8182         uint32 *out_max_value_len = &r_u->valuesize;
8183         uint16 **out_value       = &r_u->value;
8184         uint32 *out_value_len    = &r_u->realvaluesize;
8185         uint32 *out_type         = &r_u->type;
8186         uint32 *out_max_data_len = &r_u->datasize;
8187         uint8  **data_out        = &r_u->data;
8188         uint32 *out_data_len     = &r_u->realdatasize;
8189
8190         NT_PRINTER_INFO_LEVEL *printer = NULL;
8191
8192         uint32          biggest_valuesize;
8193         uint32          biggest_datasize;
8194         uint32          data_len;
8195         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8196         int             snum;
8197         WERROR          result;
8198         REGISTRY_VALUE  *val = NULL;
8199         NT_PRINTER_DATA *p_data;
8200         int             i, key_index, num_values;
8201         int             name_length;
8202
8203         *out_type = 0;
8204
8205         *out_max_data_len = 0;
8206         *data_out         = NULL;
8207         *out_data_len     = 0;
8208
8209         DEBUG(5,("spoolss_enumprinterdata\n"));
8210
8211         if (!Printer) {
8212                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8213                 return WERR_BADFID;
8214         }
8215
8216         if (!get_printer_snum(p,handle, &snum, NULL))
8217                 return WERR_BADFID;
8218
8219         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8220         if (!W_ERROR_IS_OK(result))
8221                 return result;
8222
8223         p_data = printer->info_2->data;
8224         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8225
8226         result = WERR_OK;
8227
8228         /*
8229          * The NT machine wants to know the biggest size of value and data
8230          *
8231          * cf: MSDN EnumPrinterData remark section
8232          */
8233
8234         if ( !in_value_len && !in_data_len && (key_index != -1) )
8235         {
8236                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8237
8238                 biggest_valuesize = 0;
8239                 biggest_datasize  = 0;
8240
8241                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8242
8243                 for ( i=0; i<num_values; i++ )
8244                 {
8245                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8246
8247                         name_length = strlen(val->valuename);
8248                         if ( strlen(val->valuename) > biggest_valuesize )
8249                                 biggest_valuesize = name_length;
8250
8251                         if ( val->size > biggest_datasize )
8252                                 biggest_datasize = val->size;
8253
8254                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8255                                 biggest_datasize));
8256                 }
8257
8258                 /* the value is an UNICODE string but real_value_size is the length
8259                    in bytes including the trailing 0 */
8260
8261                 *out_value_len = 2 * (1+biggest_valuesize);
8262                 *out_data_len  = biggest_datasize;
8263
8264                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8265
8266                 goto done;
8267         }
8268
8269         /*
8270          * the value len is wrong in NT sp3
8271          * that's the number of bytes not the number of unicode chars
8272          */
8273
8274         if ( key_index != -1 )
8275                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8276
8277         if ( !val )
8278         {
8279
8280                 /* out_value should default to "" or else NT4 has
8281                    problems unmarshalling the response */
8282
8283                 *out_max_value_len=(in_value_len/sizeof(uint16));
8284
8285                 if (in_value_len) {
8286                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8287                         {
8288                                 result = WERR_NOMEM;
8289                                 goto done;
8290                         }
8291                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8292                 } else {
8293                         *out_value=NULL;
8294                         *out_value_len = 0;
8295                 }
8296
8297                 /* the data is counted in bytes */
8298
8299                 *out_max_data_len = in_data_len;
8300                 *out_data_len     = in_data_len;
8301
8302                 /* only allocate when given a non-zero data_len */
8303
8304                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8305                 {
8306                         result = WERR_NOMEM;
8307                         goto done;
8308                 }
8309
8310                 result = WERR_NO_MORE_ITEMS;
8311         }
8312         else
8313         {
8314                 /*
8315                  * the value is:
8316                  * - counted in bytes in the request
8317                  * - counted in UNICODE chars in the max reply
8318                  * - counted in bytes in the real size
8319                  *
8320                  * take a pause *before* coding not *during* coding
8321                  */
8322
8323                 /* name */
8324                 *out_max_value_len=(in_value_len/sizeof(uint16));
8325                 if (in_value_len) {
8326                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8327                         {
8328                                 result = WERR_NOMEM;
8329                                 goto done;
8330                         }
8331
8332                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8333                 } else {
8334                         *out_value = NULL;
8335                         *out_value_len = 0;
8336                 }
8337
8338                 /* type */
8339
8340                 *out_type = regval_type( val );
8341
8342                 /* data - counted in bytes */
8343
8344                 *out_max_data_len = in_data_len;
8345                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8346                 {
8347                         result = WERR_NOMEM;
8348                         goto done;
8349                 }
8350                 data_len = regval_size(val);
8351                 if ( *data_out && data_len )
8352                         memcpy( *data_out, regval_data_p(val), data_len );
8353                 *out_data_len = data_len;
8354         }
8355
8356 done:
8357         free_a_printer(&printer, 2);
8358         return result;
8359 }
8360
8361 /****************************************************************************
8362 ****************************************************************************/
8363
8364 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8365 {
8366         POLICY_HND              *handle = &q_u->handle;
8367         UNISTR2                 *value = &q_u->value;
8368         uint32                  type = q_u->type;
8369         uint8                   *data = q_u->data;
8370         uint32                  real_len = q_u->real_len;
8371
8372         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8373         int                     snum=0;
8374         WERROR                  status = WERR_OK;
8375         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8376         fstring                 valuename;
8377
8378         DEBUG(5,("spoolss_setprinterdata\n"));
8379
8380         if (!Printer) {
8381                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8382                 return WERR_BADFID;
8383         }
8384
8385         if ( Printer->printer_type == SPLHND_SERVER ) {
8386                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8387                 return WERR_INVALID_PARAM;
8388         }
8389
8390         if (!get_printer_snum(p,handle, &snum, NULL))
8391                 return WERR_BADFID;
8392
8393         /*
8394          * Access check : NT returns "access denied" if you make a
8395          * SetPrinterData call without the necessary privildge.
8396          * we were originally returning OK if nothing changed
8397          * which made Win2k issue **a lot** of SetPrinterData
8398          * when connecting to a printer  --jerry
8399          */
8400
8401         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8402         {
8403                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8404                 status = WERR_ACCESS_DENIED;
8405                 goto done;
8406         }
8407
8408         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8409         if (!W_ERROR_IS_OK(status))
8410                 return status;
8411
8412         unistr2_to_ascii(valuename, value, sizeof(valuename));
8413
8414         /*
8415          * When client side code sets a magic printer data key, detect it and save
8416          * the current printer data and the magic key's data (its the DEVMODE) for
8417          * future printer/driver initializations.
8418          */
8419         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8420         {
8421                 /* Set devmode and printer initialization info */
8422                 status = save_driver_init( printer, 2, data, real_len );
8423
8424                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8425         }
8426         else
8427         {
8428         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8429                                         type, data, real_len );
8430                 if ( W_ERROR_IS_OK(status) )
8431                         status = mod_a_printer(printer, 2);
8432         }
8433
8434 done:
8435         free_a_printer(&printer, 2);
8436
8437         return status;
8438 }
8439
8440 /****************************************************************
8441  _spoolss_ResetPrinter
8442 ****************************************************************/
8443
8444 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8445                              struct spoolss_ResetPrinter *r)
8446 {
8447         POLICY_HND      *handle = r->in.handle;
8448         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8449         int             snum;
8450
8451         DEBUG(5,("_spoolss_ResetPrinter\n"));
8452
8453         /*
8454          * All we do is to check to see if the handle and queue is valid.
8455          * This call really doesn't mean anything to us because we only
8456          * support RAW printing.   --jerry
8457          */
8458
8459         if (!Printer) {
8460                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8461                         OUR_HANDLE(handle)));
8462                 return WERR_BADFID;
8463         }
8464
8465         if (!get_printer_snum(p,handle, &snum, NULL))
8466                 return WERR_BADFID;
8467
8468
8469         /* blindly return success */
8470         return WERR_OK;
8471 }
8472
8473 /****************************************************************
8474  _spoolss_DeletePrinterData
8475 ****************************************************************/
8476
8477 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8478                                   struct spoolss_DeletePrinterData *r)
8479 {
8480         POLICY_HND      *handle = r->in.handle;
8481         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8482         int             snum=0;
8483         WERROR          status = WERR_OK;
8484         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8485
8486         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8487
8488         if (!Printer) {
8489                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8490                         OUR_HANDLE(handle)));
8491                 return WERR_BADFID;
8492         }
8493
8494         if (!get_printer_snum(p, handle, &snum, NULL))
8495                 return WERR_BADFID;
8496
8497         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8498                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8499                         "printer properties change denied by handle\n"));
8500                 return WERR_ACCESS_DENIED;
8501         }
8502
8503         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8504         if (!W_ERROR_IS_OK(status))
8505                 return status;
8506
8507         if (!r->in.value_name) {
8508                 free_a_printer(&printer, 2);
8509                 return WERR_NOMEM;
8510         }
8511
8512         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8513                                         r->in.value_name );
8514
8515         if ( W_ERROR_IS_OK(status) )
8516                 mod_a_printer( printer, 2 );
8517
8518         free_a_printer(&printer, 2);
8519
8520         return status;
8521 }
8522
8523 /****************************************************************
8524  _spoolss_AddForm
8525 ****************************************************************/
8526
8527 WERROR _spoolss_AddForm(pipes_struct *p,
8528                         struct spoolss_AddForm *r)
8529 {
8530         POLICY_HND *handle = r->in.handle;
8531         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8532         nt_forms_struct tmpForm;
8533         int snum;
8534         WERROR status = WERR_OK;
8535         NT_PRINTER_INFO_LEVEL *printer = NULL;
8536
8537         int count=0;
8538         nt_forms_struct *list=NULL;
8539         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8540
8541         DEBUG(5,("_spoolss_AddForm\n"));
8542
8543         if (!Printer) {
8544                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8545                         OUR_HANDLE(handle)));
8546                 return WERR_BADFID;
8547         }
8548
8549
8550         /* forms can be added on printer of on the print server handle */
8551
8552         if ( Printer->printer_type == SPLHND_PRINTER )
8553         {
8554                 if (!get_printer_snum(p,handle, &snum, NULL))
8555                         return WERR_BADFID;
8556
8557                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8558                 if (!W_ERROR_IS_OK(status))
8559                         goto done;
8560         }
8561
8562         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8563                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8564                 status = WERR_ACCESS_DENIED;
8565                 goto done;
8566         }
8567
8568         /* can't add if builtin */
8569
8570         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8571                 status = WERR_FILE_EXISTS;
8572                 goto done;
8573         }
8574
8575         count = get_ntforms(&list);
8576
8577         if(!add_a_form(&list, form, &count)) {
8578                 status =  WERR_NOMEM;
8579                 goto done;
8580         }
8581
8582         write_ntforms(&list, count);
8583
8584         /*
8585          * ChangeID must always be set if this is a printer
8586          */
8587
8588         if ( Printer->printer_type == SPLHND_PRINTER )
8589                 status = mod_a_printer(printer, 2);
8590
8591 done:
8592         if ( printer )
8593                 free_a_printer(&printer, 2);
8594         SAFE_FREE(list);
8595
8596         return status;
8597 }
8598
8599 /****************************************************************
8600  _spoolss_DeleteForm
8601 ****************************************************************/
8602
8603 WERROR _spoolss_DeleteForm(pipes_struct *p,
8604                            struct spoolss_DeleteForm *r)
8605 {
8606         POLICY_HND *handle = r->in.handle;
8607         const char *form_name = r->in.form_name;
8608         nt_forms_struct tmpForm;
8609         int count=0;
8610         nt_forms_struct *list=NULL;
8611         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8612         int snum;
8613         WERROR status = WERR_OK;
8614         NT_PRINTER_INFO_LEVEL *printer = NULL;
8615
8616         DEBUG(5,("_spoolss_DeleteForm\n"));
8617
8618         if (!Printer) {
8619                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8620                         OUR_HANDLE(handle)));
8621                 return WERR_BADFID;
8622         }
8623
8624         /* forms can be deleted on printer of on the print server handle */
8625
8626         if ( Printer->printer_type == SPLHND_PRINTER )
8627         {
8628                 if (!get_printer_snum(p,handle, &snum, NULL))
8629                         return WERR_BADFID;
8630
8631                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8632                 if (!W_ERROR_IS_OK(status))
8633                         goto done;
8634         }
8635
8636         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8637                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8638                 status = WERR_ACCESS_DENIED;
8639                 goto done;
8640         }
8641
8642         /* can't delete if builtin */
8643
8644         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8645                 status = WERR_INVALID_PARAM;
8646                 goto done;
8647         }
8648
8649         count = get_ntforms(&list);
8650
8651         if ( !delete_a_form(&list, form_name, &count, &status ))
8652                 goto done;
8653
8654         /*
8655          * ChangeID must always be set if this is a printer
8656          */
8657
8658         if ( Printer->printer_type == SPLHND_PRINTER )
8659                 status = mod_a_printer(printer, 2);
8660
8661 done:
8662         if ( printer )
8663                 free_a_printer(&printer, 2);
8664         SAFE_FREE(list);
8665
8666         return status;
8667 }
8668
8669 /****************************************************************
8670  _spoolss_SetForm
8671 ****************************************************************/
8672
8673 WERROR _spoolss_SetForm(pipes_struct *p,
8674                         struct spoolss_SetForm *r)
8675 {
8676         POLICY_HND *handle = r->in.handle;
8677         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8678         nt_forms_struct tmpForm;
8679         int snum;
8680         WERROR status = WERR_OK;
8681         NT_PRINTER_INFO_LEVEL *printer = NULL;
8682
8683         int count=0;
8684         nt_forms_struct *list=NULL;
8685         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8686
8687         DEBUG(5,("_spoolss_SetForm\n"));
8688
8689         if (!Printer) {
8690                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8691                         OUR_HANDLE(handle)));
8692                 return WERR_BADFID;
8693         }
8694
8695         /* forms can be modified on printer of on the print server handle */
8696
8697         if ( Printer->printer_type == SPLHND_PRINTER )
8698         {
8699                 if (!get_printer_snum(p,handle, &snum, NULL))
8700                         return WERR_BADFID;
8701
8702                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8703                 if (!W_ERROR_IS_OK(status))
8704                         goto done;
8705         }
8706
8707         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8708                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8709                 status = WERR_ACCESS_DENIED;
8710                 goto done;
8711         }
8712
8713         /* can't set if builtin */
8714         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8715                 status = WERR_INVALID_PARAM;
8716                 goto done;
8717         }
8718
8719         count = get_ntforms(&list);
8720         update_a_form(&list, form, count);
8721         write_ntforms(&list, count);
8722
8723         /*
8724          * ChangeID must always be set if this is a printer
8725          */
8726
8727         if ( Printer->printer_type == SPLHND_PRINTER )
8728                 status = mod_a_printer(printer, 2);
8729
8730
8731 done:
8732         if ( printer )
8733                 free_a_printer(&printer, 2);
8734         SAFE_FREE(list);
8735
8736         return status;
8737 }
8738
8739 /****************************************************************************
8740  fill_print_processor1
8741 ****************************************************************************/
8742
8743 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8744                                     struct spoolss_PrintProcessorInfo1 *r,
8745                                     const char *print_processor_name)
8746 {
8747         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8748         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8749
8750         return WERR_OK;
8751 }
8752
8753 /****************************************************************************
8754  enumprintprocessors level 1.
8755 ****************************************************************************/
8756
8757 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8758                                           union spoolss_PrintProcessorInfo **info_p,
8759                                           uint32_t *count)
8760 {
8761         union spoolss_PrintProcessorInfo *info;
8762         WERROR result;
8763
8764         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8765         W_ERROR_HAVE_NO_MEMORY(info);
8766
8767         *count = 1;
8768
8769         result = fill_print_processor1(info, &info[0].info1, "winprint");
8770         if (!W_ERROR_IS_OK(result)) {
8771                 goto out;
8772         }
8773
8774  out:
8775         if (!W_ERROR_IS_OK(result)) {
8776                 TALLOC_FREE(info);
8777                 *count = 0;
8778                 return result;
8779         }
8780
8781         *info_p = info;
8782
8783         return WERR_OK;
8784 }
8785
8786 /****************************************************************
8787  _spoolss_EnumPrintProcessors
8788 ****************************************************************/
8789
8790 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8791                                     struct spoolss_EnumPrintProcessors *r)
8792 {
8793         WERROR result;
8794
8795         /* that's an [in out] buffer */
8796
8797         if (!r->in.buffer && (r->in.offered != 0)) {
8798                 return WERR_INVALID_PARAM;
8799         }
8800
8801         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8802
8803         /*
8804          * Enumerate the print processors ...
8805          *
8806          * Just reply with "winprint", to keep NT happy
8807          * and I can use my nice printer checker.
8808          */
8809
8810         *r->out.count = 0;
8811         *r->out.needed = 0;
8812         *r->out.info = NULL;
8813
8814         switch (r->in.level) {
8815         case 1:
8816                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8817                                                      r->out.count);
8818                 break;
8819         default:
8820                 return WERR_UNKNOWN_LEVEL;
8821         }
8822
8823         if (!W_ERROR_IS_OK(result)) {
8824                 return result;
8825         }
8826
8827         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8828                                                      spoolss_EnumPrintProcessors, NULL,
8829                                                      *r->out.info, r->in.level,
8830                                                      *r->out.count);
8831         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8832         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8833
8834         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8835 }
8836
8837 /****************************************************************************
8838  fill_printprocdatatype1
8839 ****************************************************************************/
8840
8841 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8842                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8843                                       const char *name_array)
8844 {
8845         r->name_array = talloc_strdup(mem_ctx, name_array);
8846         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8847
8848         return WERR_OK;
8849 }
8850
8851 /****************************************************************************
8852  enumprintprocdatatypes level 1.
8853 ****************************************************************************/
8854
8855 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8856                                              union spoolss_PrintProcDataTypesInfo **info_p,
8857                                              uint32_t *count)
8858 {
8859         WERROR result;
8860         union spoolss_PrintProcDataTypesInfo *info;
8861
8862         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8863         W_ERROR_HAVE_NO_MEMORY(info);
8864
8865         *count = 1;
8866
8867         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8868         if (!W_ERROR_IS_OK(result)) {
8869                 goto out;
8870         }
8871
8872  out:
8873         if (!W_ERROR_IS_OK(result)) {
8874                 TALLOC_FREE(info);
8875                 *count = 0;
8876                 return result;
8877         }
8878
8879         *info_p = info;
8880
8881         return WERR_OK;
8882 }
8883
8884 /****************************************************************
8885  _spoolss_EnumPrintProcDataTypes
8886 ****************************************************************/
8887
8888 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8889                                        struct spoolss_EnumPrintProcDataTypes *r)
8890 {
8891         WERROR result;
8892
8893         /* that's an [in out] buffer */
8894
8895         if (!r->in.buffer && (r->in.offered != 0)) {
8896                 return WERR_INVALID_PARAM;
8897         }
8898
8899         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8900
8901         *r->out.count = 0;
8902         *r->out.needed = 0;
8903         *r->out.info = NULL;
8904
8905         switch (r->in.level) {
8906         case 1:
8907                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8908                                                         r->out.count);
8909                 break;
8910         default:
8911                 return WERR_UNKNOWN_LEVEL;
8912         }
8913
8914         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8915                                                      spoolss_EnumPrintProcDataTypes, NULL,
8916                                                      *r->out.info, r->in.level,
8917                                                      *r->out.count);
8918         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8919         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8920
8921         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8922 }
8923
8924 /****************************************************************************
8925  fill_monitor_1
8926 ****************************************************************************/
8927
8928 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8929                              struct spoolss_MonitorInfo1 *r,
8930                              const char *monitor_name)
8931 {
8932         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8933         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8934
8935         return WERR_OK;
8936 }
8937
8938 /****************************************************************************
8939  fill_monitor_2
8940 ****************************************************************************/
8941
8942 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8943                              struct spoolss_MonitorInfo2 *r,
8944                              const char *monitor_name,
8945                              const char *environment,
8946                              const char *dll_name)
8947 {
8948         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8949         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8950         r->environment                  = talloc_strdup(mem_ctx, environment);
8951         W_ERROR_HAVE_NO_MEMORY(r->environment);
8952         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8953         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8954
8955         return WERR_OK;
8956 }
8957
8958 /****************************************************************************
8959  enumprintmonitors level 1.
8960 ****************************************************************************/
8961
8962 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8963                                         union spoolss_MonitorInfo **info_p,
8964                                         uint32_t *count)
8965 {
8966         union spoolss_MonitorInfo *info;
8967         WERROR result = WERR_OK;
8968
8969         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8970         W_ERROR_HAVE_NO_MEMORY(info);
8971
8972         *count = 2;
8973
8974         result = fill_monitor_1(info, &info[0].info1,
8975                                 SPL_LOCAL_PORT /* FIXME */);
8976         if (!W_ERROR_IS_OK(result)) {
8977                 goto out;
8978         }
8979
8980         result = fill_monitor_1(info, &info[1].info1,
8981                                 SPL_TCPIP_PORT /* FIXME */);
8982         if (!W_ERROR_IS_OK(result)) {
8983                 goto out;
8984         }
8985
8986 out:
8987         if (!W_ERROR_IS_OK(result)) {
8988                 TALLOC_FREE(info);
8989                 *count = 0;
8990                 return result;
8991         }
8992
8993         *info_p = info;
8994
8995         return WERR_OK;
8996 }
8997
8998 /****************************************************************************
8999  enumprintmonitors level 2.
9000 ****************************************************************************/
9001
9002 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9003                                         union spoolss_MonitorInfo **info_p,
9004                                         uint32_t *count)
9005 {
9006         union spoolss_MonitorInfo *info;
9007         WERROR result = WERR_OK;
9008
9009         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9010         W_ERROR_HAVE_NO_MEMORY(info);
9011
9012         *count = 2;
9013
9014         result = fill_monitor_2(info, &info[0].info2,
9015                                 SPL_LOCAL_PORT, /* FIXME */
9016                                 "Windows NT X86", /* FIXME */
9017                                 "localmon.dll");
9018         if (!W_ERROR_IS_OK(result)) {
9019                 goto out;
9020         }
9021
9022         result = fill_monitor_2(info, &info[1].info2,
9023                                 SPL_TCPIP_PORT, /* FIXME */
9024                                 "Windows NT X86", /* FIXME */
9025                                 "tcpmon.dll");
9026         if (!W_ERROR_IS_OK(result)) {
9027                 goto out;
9028         }
9029
9030 out:
9031         if (!W_ERROR_IS_OK(result)) {
9032                 TALLOC_FREE(info);
9033                 *count = 0;
9034                 return result;
9035         }
9036
9037         *info_p = info;
9038
9039         return WERR_OK;
9040 }
9041
9042 /****************************************************************
9043  _spoolss_EnumMonitors
9044 ****************************************************************/
9045
9046 WERROR _spoolss_EnumMonitors(pipes_struct *p,
9047                              struct spoolss_EnumMonitors *r)
9048 {
9049         WERROR result;
9050
9051         /* that's an [in out] buffer */
9052
9053         if (!r->in.buffer && (r->in.offered != 0)) {
9054                 return WERR_INVALID_PARAM;
9055         }
9056
9057         DEBUG(5,("_spoolss_EnumMonitors\n"));
9058
9059         /*
9060          * Enumerate the print monitors ...
9061          *
9062          * Just reply with "Local Port", to keep NT happy
9063          * and I can use my nice printer checker.
9064          */
9065
9066         *r->out.count = 0;
9067         *r->out.needed = 0;
9068         *r->out.info = NULL;
9069
9070         switch (r->in.level) {
9071         case 1:
9072                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9073                                                    r->out.count);
9074                 break;
9075         case 2:
9076                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9077                                                    r->out.count);
9078                 break;
9079         default:
9080                 return WERR_UNKNOWN_LEVEL;
9081         }
9082
9083         if (!W_ERROR_IS_OK(result)) {
9084                 return result;
9085         }
9086
9087         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9088                                                      spoolss_EnumMonitors, NULL,
9089                                                      *r->out.info, r->in.level,
9090                                                      *r->out.count);
9091         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9092         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9093
9094         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9095 }
9096
9097 /****************************************************************************
9098 ****************************************************************************/
9099
9100 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9101                              NT_PRINTER_INFO_LEVEL *ntprinter,
9102                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9103                              uint32 *needed)
9104 {
9105         int i=0;
9106         bool found=False;
9107         JOB_INFO_1 *info_1=NULL;
9108         WERROR result = WERR_OK;
9109
9110         info_1=SMB_MALLOC_P(JOB_INFO_1);
9111
9112         if (info_1 == NULL) {
9113                 return WERR_NOMEM;
9114         }
9115
9116         for (i=0; i<count && found==False; i++) {
9117                 if ((*queue)[i].job==(int)jobid)
9118                         found=True;
9119         }
9120
9121         if (found==False) {
9122                 SAFE_FREE(info_1);
9123                 /* NT treats not found as bad param... yet another bad choice */
9124                 return WERR_INVALID_PARAM;
9125         }
9126
9127         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9128
9129         *needed += spoolss_size_job_info_1(info_1);
9130
9131         if (*needed > offered) {
9132                 result = WERR_INSUFFICIENT_BUFFER;
9133                 goto out;
9134         }
9135
9136         if (!rpcbuf_alloc_size(buffer, *needed)) {
9137                 result = WERR_NOMEM;
9138                 goto out;
9139         }
9140
9141         smb_io_job_info_1("", buffer, info_1, 0);
9142
9143 out:
9144         SAFE_FREE(info_1);
9145
9146         return result;
9147 }
9148
9149 /****************************************************************************
9150 ****************************************************************************/
9151
9152 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9153                              NT_PRINTER_INFO_LEVEL *ntprinter,
9154                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9155                              uint32 *needed)
9156 {
9157         int             i = 0;
9158         bool            found = False;
9159         JOB_INFO_2      *info_2;
9160         WERROR          result;
9161         DEVICEMODE      *devmode = NULL;
9162         NT_DEVICEMODE   *nt_devmode = NULL;
9163
9164         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9165                 return WERR_NOMEM;
9166
9167         ZERO_STRUCTP(info_2);
9168
9169         for ( i=0; i<count && found==False; i++ )
9170         {
9171                 if ((*queue)[i].job == (int)jobid)
9172                         found = True;
9173         }
9174
9175         if ( !found ) {
9176                 /* NT treats not found as bad param... yet another bad
9177                    choice */
9178                 result = WERR_INVALID_PARAM;
9179                 goto done;
9180         }
9181
9182         /*
9183          * if the print job does not have a DEVMODE associated with it,
9184          * just use the one for the printer. A NULL devicemode is not
9185          *  a failure condition
9186          */
9187
9188         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9189                 devmode = construct_dev_mode(lp_const_servicename(snum));
9190         else {
9191                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9192                         ZERO_STRUCTP( devmode );
9193                         convert_nt_devicemode( devmode, nt_devmode );
9194                 }
9195         }
9196
9197         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9198
9199         *needed += spoolss_size_job_info_2(info_2);
9200
9201         if (*needed > offered) {
9202                 result = WERR_INSUFFICIENT_BUFFER;
9203                 goto done;
9204         }
9205
9206         if (!rpcbuf_alloc_size(buffer, *needed)) {
9207                 result = WERR_NOMEM;
9208                 goto done;
9209         }
9210
9211         smb_io_job_info_2("", buffer, info_2, 0);
9212
9213         result = WERR_OK;
9214
9215  done:
9216         /* Cleanup allocated memory */
9217
9218         free_job_info_2(info_2);        /* Also frees devmode */
9219         SAFE_FREE(info_2);
9220
9221         return result;
9222 }
9223
9224 /****************************************************************************
9225 ****************************************************************************/
9226
9227 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9228 {
9229         POLICY_HND *handle = &q_u->handle;
9230         uint32 jobid = q_u->jobid;
9231         uint32 level = q_u->level;
9232         RPC_BUFFER *buffer = NULL;
9233         uint32 offered = q_u->offered;
9234         uint32 *needed = &r_u->needed;
9235         WERROR          wstatus = WERR_OK;
9236         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9237         int snum;
9238         int count;
9239         print_queue_struct      *queue = NULL;
9240         print_status_struct prt_status;
9241
9242         /* that's an [in out] buffer */
9243
9244         if (!q_u->buffer && (offered!=0)) {
9245                 return WERR_INVALID_PARAM;
9246         }
9247
9248         if (offered > MAX_RPC_DATA_SIZE) {
9249                 return WERR_INVALID_PARAM;
9250         }
9251
9252         rpcbuf_move(q_u->buffer, &r_u->buffer);
9253         buffer = r_u->buffer;
9254
9255         DEBUG(5,("spoolss_getjob\n"));
9256
9257         *needed = 0;
9258
9259         if (!get_printer_snum(p, handle, &snum, NULL))
9260                 return WERR_BADFID;
9261
9262         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9263         if ( !W_ERROR_IS_OK(wstatus) )
9264                 return wstatus;
9265
9266         count = print_queue_status(snum, &queue, &prt_status);
9267
9268         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9269                      count, prt_status.status, prt_status.message));
9270
9271         switch ( level ) {
9272         case 1:
9273                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9274                                 buffer, offered, needed);
9275                         break;
9276         case 2:
9277                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9278                                 buffer, offered, needed);
9279                         break;
9280         default:
9281                         wstatus = WERR_UNKNOWN_LEVEL;
9282                         break;
9283         }
9284
9285         SAFE_FREE(queue);
9286         free_a_printer( &ntprinter, 2 );
9287
9288         return wstatus;
9289 }
9290
9291 /****************************************************************
9292  _spoolss_GetPrinterDataEx
9293
9294  From MSDN documentation of GetPrinterDataEx: pass request
9295  to GetPrinterData if key is "PrinterDriverData".
9296 ****************************************************************/
9297
9298 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9299                                  struct spoolss_GetPrinterDataEx *r)
9300 {
9301         POLICY_HND      *handle = r->in.handle;
9302         uint8           *data = NULL;
9303         const char      *keyname = r->in.key_name;
9304         const char      *valuename = r->in.value_name;
9305
9306         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9307
9308         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9309         int                     snum = 0;
9310         WERROR                  status = WERR_OK;
9311
9312         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9313
9314         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9315                 keyname, valuename));
9316
9317         /* in case of problem, return some default values */
9318
9319         *r->out.needed  = 0;
9320         *r->out.type    = 0;
9321
9322         if (!Printer) {
9323                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9324                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9325                 status = WERR_BADFID;
9326                 goto done;
9327         }
9328
9329         /* Is the handle to a printer or to the server? */
9330
9331         if (Printer->printer_type == SPLHND_SERVER) {
9332                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9333                         "Not implemented for server handles yet\n"));
9334                 status = WERR_INVALID_PARAM;
9335                 goto done;
9336         }
9337
9338         if ( !get_printer_snum(p,handle, &snum, NULL) )
9339                 return WERR_BADFID;
9340
9341         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9342         if ( !W_ERROR_IS_OK(status) )
9343                 goto done;
9344
9345         /* check to see if the keyname is valid */
9346         if ( !strlen(keyname) ) {
9347                 status = WERR_INVALID_PARAM;
9348                 goto done;
9349         }
9350
9351         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9352                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9353                         "Invalid keyname [%s]\n", keyname ));
9354                 free_a_printer( &printer, 2 );
9355                 status = WERR_BADFILE;
9356                 goto done;
9357         }
9358
9359         /* When given a new keyname, we should just create it */
9360
9361         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9362                                      r->out.type, &data, r->out.needed,
9363                                      r->in.offered );
9364
9365         if (*r->out.needed > r->in.offered) {
9366                 status = WERR_MORE_DATA;
9367         }
9368
9369         if (W_ERROR_IS_OK(status)) {
9370                 memcpy(r->out.buffer, data, r->in.offered);
9371         }
9372
9373 done:
9374         if ( printer )
9375         free_a_printer( &printer, 2 );
9376
9377         return status;
9378 }
9379
9380 /****************************************************************
9381  _spoolss_SetPrinterDataEx
9382 ****************************************************************/
9383
9384 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9385                                  struct spoolss_SetPrinterDataEx *r)
9386 {
9387         POLICY_HND              *handle = r->in.handle;
9388         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9389         int                     snum = 0;
9390         WERROR                  status = WERR_OK;
9391         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9392         char                    *oid_string;
9393
9394         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9395
9396         /* From MSDN documentation of SetPrinterDataEx: pass request to
9397            SetPrinterData if key is "PrinterDriverData" */
9398
9399         if (!Printer) {
9400                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9401                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9402                 return WERR_BADFID;
9403         }
9404
9405         if ( Printer->printer_type == SPLHND_SERVER ) {
9406                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9407                         "Not implemented for server handles yet\n"));
9408                 return WERR_INVALID_PARAM;
9409         }
9410
9411         if ( !get_printer_snum(p,handle, &snum, NULL) )
9412                 return WERR_BADFID;
9413
9414         /*
9415          * Access check : NT returns "access denied" if you make a
9416          * SetPrinterData call without the necessary privildge.
9417          * we were originally returning OK if nothing changed
9418          * which made Win2k issue **a lot** of SetPrinterData
9419          * when connecting to a printer  --jerry
9420          */
9421
9422         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9423         {
9424                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9425                         "change denied by handle access permissions\n"));
9426                 return WERR_ACCESS_DENIED;
9427         }
9428
9429         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9430         if (!W_ERROR_IS_OK(status))
9431                 return status;
9432
9433         /* check for OID in valuename */
9434
9435         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9436         {
9437                 *oid_string = '\0';
9438                 oid_string++;
9439         }
9440
9441         /* save the registry data */
9442
9443         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9444                                      r->in.type, r->in.buffer, r->in.offered );
9445
9446         if ( W_ERROR_IS_OK(status) )
9447         {
9448                 /* save the OID if one was specified */
9449                 if ( oid_string ) {
9450                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9451                                 r->in.key_name, SPOOL_OID_KEY);
9452                         if (!str) {
9453                                 return WERR_NOMEM;
9454                         }
9455
9456                         /*
9457                          * I'm not checking the status here on purpose.  Don't know
9458                          * if this is right, but I'm returning the status from the
9459                          * previous set_printer_dataex() call.  I have no idea if
9460                          * this is right.    --jerry
9461                          */
9462
9463                         set_printer_dataex( printer, str, r->in.value_name,
9464                                             REG_SZ, (uint8 *)oid_string,
9465                                             strlen(oid_string)+1 );
9466                 }
9467
9468                 status = mod_a_printer(printer, 2);
9469         }
9470
9471         free_a_printer(&printer, 2);
9472
9473         return status;
9474 }
9475
9476 /****************************************************************
9477  _spoolss_DeletePrinterDataEx
9478 ****************************************************************/
9479
9480 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9481                                     struct spoolss_DeletePrinterDataEx *r)
9482 {
9483         POLICY_HND      *handle = r->in.handle;
9484         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9485         int             snum=0;
9486         WERROR          status = WERR_OK;
9487         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9488
9489         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9490
9491         if (!Printer) {
9492                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9493                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9494                 return WERR_BADFID;
9495         }
9496
9497         if (!get_printer_snum(p, handle, &snum, NULL))
9498                 return WERR_BADFID;
9499
9500         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9501                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9502                         "printer properties change denied by handle\n"));
9503                 return WERR_ACCESS_DENIED;
9504         }
9505
9506         if (!r->in.value_name || !r->in.key_name) {
9507                 return WERR_NOMEM;
9508         }
9509
9510         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9511         if (!W_ERROR_IS_OK(status))
9512                 return status;
9513
9514         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9515
9516         if ( W_ERROR_IS_OK(status) )
9517                 mod_a_printer( printer, 2 );
9518
9519         free_a_printer(&printer, 2);
9520
9521         return status;
9522 }
9523
9524 /********************************************************************
9525  * spoolss_enumprinterkey
9526  ********************************************************************/
9527
9528
9529 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9530 {
9531         fstring         key;
9532         fstring         *keynames = NULL;
9533         uint16          *enumkeys = NULL;
9534         int             num_keys;
9535         int             printerkey_len;
9536         POLICY_HND      *handle = &q_u->handle;
9537         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9538         NT_PRINTER_DATA *data;
9539         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9540         int             snum = 0;
9541         WERROR          status = WERR_BADFILE;
9542
9543
9544         DEBUG(4,("_spoolss_enumprinterkey\n"));
9545
9546         if (!Printer) {
9547                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9548                 return WERR_BADFID;
9549         }
9550
9551         if ( !get_printer_snum(p,handle, &snum, NULL) )
9552                 return WERR_BADFID;
9553
9554         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9555         if (!W_ERROR_IS_OK(status))
9556                 return status;
9557
9558         /* get the list of subkey names */
9559
9560         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9561         data = printer->info_2->data;
9562
9563         num_keys = get_printer_subkeys( data, key, &keynames );
9564
9565         if ( num_keys == -1 ) {
9566                 status = WERR_BADFILE;
9567                 goto done;
9568         }
9569
9570         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9571
9572         r_u->needed = printerkey_len*2;
9573
9574         if ( q_u->size < r_u->needed ) {
9575                 status = WERR_MORE_DATA;
9576                 goto done;
9577         }
9578
9579         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9580                 status = WERR_NOMEM;
9581                 goto done;
9582         }
9583
9584         status = WERR_OK;
9585
9586         if ( q_u->size < r_u->needed )
9587                 status = WERR_MORE_DATA;
9588
9589 done:
9590         free_a_printer( &printer, 2 );
9591         SAFE_FREE( keynames );
9592
9593         return status;
9594 }
9595
9596 /****************************************************************
9597  _spoolss_DeletePrinterKey
9598 ****************************************************************/
9599
9600 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9601                                  struct spoolss_DeletePrinterKey *r)
9602 {
9603         POLICY_HND              *handle = r->in.handle;
9604         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9605         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9606         int                     snum=0;
9607         WERROR                  status;
9608
9609         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9610
9611         if (!Printer) {
9612                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9613                         OUR_HANDLE(handle)));
9614                 return WERR_BADFID;
9615         }
9616
9617         /* if keyname == NULL, return error */
9618
9619         if ( !r->in.key_name )
9620                 return WERR_INVALID_PARAM;
9621
9622         if (!get_printer_snum(p, handle, &snum, NULL))
9623                 return WERR_BADFID;
9624
9625         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9626                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9627                         "printer properties change denied by handle\n"));
9628                 return WERR_ACCESS_DENIED;
9629         }
9630
9631         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9632         if (!W_ERROR_IS_OK(status))
9633                 return status;
9634
9635         /* delete the key and all subneys */
9636
9637         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9638
9639         if ( W_ERROR_IS_OK(status) )
9640                 status = mod_a_printer(printer, 2);
9641
9642         free_a_printer( &printer, 2 );
9643
9644         return status;
9645 }
9646
9647
9648 /********************************************************************
9649  * spoolss_enumprinterdataex
9650  ********************************************************************/
9651
9652 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9653 {
9654         POLICY_HND      *handle = &q_u->handle;
9655         uint32          in_size = q_u->size;
9656         uint32          num_entries,
9657                         needed;
9658         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9659         PRINTER_ENUM_VALUES     *enum_values = NULL;
9660         NT_PRINTER_DATA         *p_data;
9661         fstring         key;
9662         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9663         int             snum;
9664         WERROR          result;
9665         int             key_index;
9666         int             i;
9667         REGISTRY_VALUE  *val;
9668         char            *value_name;
9669         uint32          data_len;
9670
9671
9672         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9673
9674         if (!Printer) {
9675                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9676                 return WERR_BADFID;
9677         }
9678
9679         /*
9680          * first check for a keyname of NULL or "".  Win2k seems to send
9681          * this a lot and we should send back WERR_INVALID_PARAM
9682          * no need to spend time looking up the printer in this case.
9683          * --jerry
9684          */
9685
9686         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9687         if ( !strlen(key) ) {
9688                 result = WERR_INVALID_PARAM;
9689                 goto done;
9690         }
9691
9692         /* get the printer off of disk */
9693
9694         if (!get_printer_snum(p,handle, &snum, NULL))
9695                 return WERR_BADFID;
9696
9697         ZERO_STRUCT(printer);
9698         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9699         if (!W_ERROR_IS_OK(result))
9700                 return result;
9701
9702         /* now look for a match on the key name */
9703
9704         p_data = printer->info_2->data;
9705
9706         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9707         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9708         {
9709                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9710                 result = WERR_INVALID_PARAM;
9711                 goto done;
9712         }
9713
9714         result = WERR_OK;
9715         needed = 0;
9716
9717         /* allocate the memory for the array of pointers -- if necessary */
9718
9719         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9720         if ( num_entries )
9721         {
9722                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9723                 {
9724                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9725                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9726                         result = WERR_NOMEM;
9727                         goto done;
9728                 }
9729
9730                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9731         }
9732
9733         /*
9734          * loop through all params and build the array to pass
9735          * back to the  client
9736          */
9737
9738         for ( i=0; i<num_entries; i++ )
9739         {
9740                 /* lookup the registry value */
9741
9742                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9743                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9744
9745                 /* copy the data */
9746
9747                 value_name = regval_name( val );
9748                 init_unistr( &enum_values[i].valuename, value_name );
9749                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9750                 enum_values[i].type      = regval_type( val );
9751
9752                 data_len = regval_size( val );
9753                 if ( data_len ) {
9754                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9755                         {
9756                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9757                                         data_len ));
9758                                 result = WERR_NOMEM;
9759                                 goto done;
9760                         }
9761                 }
9762                 enum_values[i].data_len = data_len;
9763
9764                 /* keep track of the size of the array in bytes */
9765
9766                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9767         }
9768
9769         /* housekeeping information in the reply */
9770
9771         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9772          * the hand marshalled container size is a multiple
9773          * of 4 bytes for RPC alignment.
9774          */
9775
9776         if (needed % 4) {
9777                 needed += 4-(needed % 4);
9778         }
9779
9780         r_u->needed     = needed;
9781         r_u->returned   = num_entries;
9782
9783         if (needed > in_size) {
9784                 result = WERR_MORE_DATA;
9785                 goto done;
9786         }
9787
9788         /* copy data into the reply */
9789
9790         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9791            response buffer size is != the offered buffer size
9792
9793                 r_u->ctr.size           = r_u->needed;
9794         */
9795         r_u->ctr.size           = in_size;
9796
9797         r_u->ctr.size_of_array  = r_u->returned;
9798         r_u->ctr.values         = enum_values;
9799
9800 done:
9801         if ( printer )
9802         free_a_printer(&printer, 2);
9803
9804         return result;
9805 }
9806
9807 /****************************************************************************
9808 ****************************************************************************/
9809
9810 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9811                                                  const char *servername,
9812                                                  const char *environment,
9813                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r,
9814                                                  uint32_t offered,
9815                                                  uint32_t *needed)
9816 {
9817         WERROR werr;
9818         char *path = NULL;
9819
9820         werr = compose_spoolss_server_path(mem_ctx,
9821                                            servername,
9822                                            environment,
9823                                            SPOOLSS_PRTPROCS_PATH,
9824                                            &path);
9825         if (!W_ERROR_IS_OK(werr)) {
9826                 return werr;
9827         }
9828
9829         DEBUG(4,("print processor directory: [%s]\n", path));
9830
9831         r->directory_name = path;
9832
9833         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9834
9835         if (*needed > offered) {
9836                 talloc_free(path);
9837                 return WERR_INSUFFICIENT_BUFFER;
9838         }
9839
9840         return WERR_OK;
9841 }
9842
9843 /****************************************************************
9844  _spoolss_GetPrintProcessorDirectory
9845 ****************************************************************/
9846
9847 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9848                                            struct spoolss_GetPrintProcessorDirectory *r)
9849 {
9850         WERROR result;
9851
9852         /* that's an [in out] buffer */
9853
9854         if (!r->in.buffer && (r->in.offered != 0)) {
9855                 return WERR_INVALID_PARAM;
9856         }
9857
9858         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9859                 r->in.level));
9860
9861         *r->out.needed = 0;
9862
9863         /* r->in.level is ignored */
9864
9865         result = getprintprocessordirectory_level_1(p->mem_ctx,
9866                                                     r->in.server,
9867                                                     r->in.environment,
9868                                                     &r->out.info->info1,
9869                                                     r->in.offered,
9870                                                     r->out.needed);
9871         if (!W_ERROR_IS_OK(result)) {
9872                 TALLOC_FREE(r->out.info);
9873         }
9874
9875         return result;
9876 }
9877
9878 /*******************************************************************
9879  ********************************************************************/
9880
9881 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9882                                const char *dllname)
9883 {
9884         enum ndr_err_code ndr_err;
9885         struct spoolss_MonitorUi ui;
9886
9887         ui.dll_name = dllname;
9888
9889         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9890                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9891         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9892                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9893         }
9894         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9895 }
9896
9897 /*******************************************************************
9898  Streams the monitor UI DLL name in UNICODE
9899 *******************************************************************/
9900
9901 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9902                                NT_USER_TOKEN *token, DATA_BLOB *in,
9903                                DATA_BLOB *out, uint32_t *needed)
9904 {
9905         const char *dllname = "tcpmonui.dll";
9906
9907         *needed = (strlen(dllname)+1) * 2;
9908
9909         if (out->length < *needed) {
9910                 return WERR_INSUFFICIENT_BUFFER;
9911         }
9912
9913         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9914                 return WERR_NOMEM;
9915         }
9916
9917         return WERR_OK;
9918 }
9919
9920 /*******************************************************************
9921  ********************************************************************/
9922
9923 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9924                              struct spoolss_PortData1 *port1,
9925                              const DATA_BLOB *buf)
9926 {
9927         enum ndr_err_code ndr_err;
9928         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9929                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9930         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9931                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9932         }
9933         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9934 }
9935
9936 /*******************************************************************
9937  ********************************************************************/
9938
9939 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9940                              struct spoolss_PortData2 *port2,
9941                              const DATA_BLOB *buf)
9942 {
9943         enum ndr_err_code ndr_err;
9944         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9945                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9946         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9947                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9948         }
9949         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9950 }
9951
9952 /*******************************************************************
9953  Create a new TCP/IP port
9954 *******************************************************************/
9955
9956 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9957                              NT_USER_TOKEN *token, DATA_BLOB *in,
9958                              DATA_BLOB *out, uint32_t *needed)
9959 {
9960         struct spoolss_PortData1 port1;
9961         struct spoolss_PortData2 port2;
9962         char *device_uri = NULL;
9963         uint32_t version;
9964
9965         const char *portname;
9966         const char *hostaddress;
9967         const char *queue;
9968         uint32_t port_number;
9969         uint32_t protocol;
9970
9971         /* peek for spoolss_PortData version */
9972
9973         if (!in || (in->length < (128 + 4))) {
9974                 return WERR_GENERAL_FAILURE;
9975         }
9976
9977         version = IVAL(in->data, 128);
9978
9979         switch (version) {
9980                 case 1:
9981                         ZERO_STRUCT(port1);
9982
9983                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9984                                 return WERR_NOMEM;
9985                         }
9986
9987                         portname        = port1.portname;
9988                         hostaddress     = port1.hostaddress;
9989                         queue           = port1.queue;
9990                         protocol        = port1.protocol;
9991                         port_number     = port1.port_number;
9992
9993                         break;
9994                 case 2:
9995                         ZERO_STRUCT(port2);
9996
9997                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9998                                 return WERR_NOMEM;
9999                         }
10000
10001                         portname        = port2.portname;
10002                         hostaddress     = port2.hostaddress;
10003                         queue           = port2.queue;
10004                         protocol        = port2.protocol;
10005                         port_number     = port2.port_number;
10006
10007                         break;
10008                 default:
10009                         DEBUG(1,("xcvtcp_addport: "
10010                                 "unknown version of port_data: %d\n", version));
10011                         return WERR_UNKNOWN_PORT;
10012         }
10013
10014         /* create the device URI and call the add_port_hook() */
10015
10016         switch (protocol) {
10017         case PROTOCOL_RAWTCP_TYPE:
10018                 device_uri = talloc_asprintf(mem_ctx,
10019                                 "socket://%s:%d/", hostaddress,
10020                                 port_number);
10021                 break;
10022
10023         case PROTOCOL_LPR_TYPE:
10024                 device_uri = talloc_asprintf(mem_ctx,
10025                         "lpr://%s/%s", hostaddress, queue );
10026                 break;
10027
10028         default:
10029                 return WERR_UNKNOWN_PORT;
10030         }
10031
10032         if (!device_uri) {
10033                 return WERR_NOMEM;
10034         }
10035
10036         return add_port_hook(mem_ctx, token, portname, device_uri);
10037 }
10038
10039 /*******************************************************************
10040 *******************************************************************/
10041
10042 struct xcv_api_table xcvtcp_cmds[] = {
10043         { "MonitorUI",  xcvtcp_monitorui },
10044         { "AddPort",    xcvtcp_addport},
10045         { NULL,         NULL }
10046 };
10047
10048 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10049                                      NT_USER_TOKEN *token, const char *command,
10050                                      DATA_BLOB *inbuf,
10051                                      DATA_BLOB *outbuf,
10052                                      uint32_t *needed )
10053 {
10054         int i;
10055
10056         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10057
10058         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10059                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10060                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10061         }
10062
10063         return WERR_BADFUNC;
10064 }
10065
10066 /*******************************************************************
10067 *******************************************************************/
10068 #if 0   /* don't support management using the "Local Port" monitor */
10069
10070 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10071                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10072                                  DATA_BLOB *out, uint32_t *needed)
10073 {
10074         const char *dllname = "localui.dll";
10075
10076         *needed = (strlen(dllname)+1) * 2;
10077
10078         if (out->length < *needed) {
10079                 return WERR_INSUFFICIENT_BUFFER;
10080         }
10081
10082         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10083                 return WERR_NOMEM;
10084         }
10085
10086         return WERR_OK;
10087 }
10088
10089 /*******************************************************************
10090 *******************************************************************/
10091
10092 struct xcv_api_table xcvlocal_cmds[] = {
10093         { "MonitorUI",  xcvlocal_monitorui },
10094         { NULL,         NULL }
10095 };
10096 #else
10097 struct xcv_api_table xcvlocal_cmds[] = {
10098         { NULL,         NULL }
10099 };
10100 #endif
10101
10102
10103
10104 /*******************************************************************
10105 *******************************************************************/
10106
10107 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10108                                        NT_USER_TOKEN *token, const char *command,
10109                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10110                                        uint32_t *needed)
10111 {
10112         int i;
10113
10114         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10115
10116         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10117                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10118                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10119         }
10120         return WERR_BADFUNC;
10121 }
10122
10123 /****************************************************************
10124  _spoolss_XcvData
10125 ****************************************************************/
10126
10127 WERROR _spoolss_XcvData(pipes_struct *p,
10128                         struct spoolss_XcvData *r)
10129 {
10130         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10131         DATA_BLOB out_data = data_blob_null;
10132         WERROR werror;
10133
10134         if (!Printer) {
10135                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10136                         OUR_HANDLE(r->in.handle)));
10137                 return WERR_BADFID;
10138         }
10139
10140         /* Has to be a handle to the TCP/IP port monitor */
10141
10142         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10143                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10144                 return WERR_BADFID;
10145         }
10146
10147         /* requires administrative access to the server */
10148
10149         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10150                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10151                 return WERR_ACCESS_DENIED;
10152         }
10153
10154         /* Allocate the outgoing buffer */
10155
10156         if (r->in.out_data_size) {
10157                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10158                 if (out_data.data == NULL) {
10159                         return WERR_NOMEM;
10160                 }
10161         }
10162
10163         switch ( Printer->printer_type ) {
10164         case SPLHND_PORTMON_TCP:
10165                 werror = process_xcvtcp_command(p->mem_ctx,
10166                                                 p->server_info->ptok,
10167                                                 r->in.function_name,
10168                                                 &r->in.in_data, &out_data,
10169                                                 r->out.needed);
10170                 break;
10171         case SPLHND_PORTMON_LOCAL:
10172                 werror = process_xcvlocal_command(p->mem_ctx,
10173                                                   p->server_info->ptok,
10174                                                   r->in.function_name,
10175                                                   &r->in.in_data, &out_data,
10176                                                   r->out.needed);
10177                 break;
10178         default:
10179                 werror = WERR_INVALID_PRINT_MONITOR;
10180         }
10181
10182         if (!W_ERROR_IS_OK(werror)) {
10183                 return werror;
10184         }
10185
10186         *r->out.status_code = 0;
10187
10188         memcpy(r->out.out_data, out_data.data, out_data.length);
10189
10190         return WERR_OK;
10191 }
10192
10193 /****************************************************************
10194  _spoolss_AddPrintProcessor
10195 ****************************************************************/
10196
10197 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10198                                   struct spoolss_AddPrintProcessor *r)
10199 {
10200         /* for now, just indicate success and ignore the add.  We'll
10201            automatically set the winprint processor for printer
10202            entries later.  Used to debug the LexMark Optra S 1855 PCL
10203            driver --jerry */
10204
10205         return WERR_OK;
10206 }
10207
10208 /****************************************************************
10209  _spoolss_EnumPrinters
10210 ****************************************************************/
10211
10212 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10213                              struct spoolss_EnumPrinters *r)
10214 {
10215         p->rng_fault_state = true;
10216         return WERR_NOT_SUPPORTED;
10217 }
10218
10219 /****************************************************************
10220  _spoolss_GetJob
10221 ****************************************************************/
10222
10223 WERROR _spoolss_GetJob(pipes_struct *p,
10224                        struct spoolss_GetJob *r)
10225 {
10226         p->rng_fault_state = true;
10227         return WERR_NOT_SUPPORTED;
10228 }
10229
10230 /****************************************************************
10231  _spoolss_EnumJobs
10232 ****************************************************************/
10233
10234 WERROR _spoolss_EnumJobs(pipes_struct *p,
10235                          struct spoolss_EnumJobs *r)
10236 {
10237         p->rng_fault_state = true;
10238         return WERR_NOT_SUPPORTED;
10239 }
10240
10241 /****************************************************************
10242  _spoolss_AddPrinter
10243 ****************************************************************/
10244
10245 WERROR _spoolss_AddPrinter(pipes_struct *p,
10246                            struct spoolss_AddPrinter *r)
10247 {
10248         p->rng_fault_state = true;
10249         return WERR_NOT_SUPPORTED;
10250 }
10251
10252 /****************************************************************
10253  _spoolss_GetPrinter
10254 ****************************************************************/
10255
10256 WERROR _spoolss_GetPrinter(pipes_struct *p,
10257                            struct spoolss_GetPrinter *r)
10258 {
10259         p->rng_fault_state = true;
10260         return WERR_NOT_SUPPORTED;
10261 }
10262
10263 /****************************************************************
10264  _spoolss_EnumPrinterDrivers
10265 ****************************************************************/
10266
10267 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10268                                    struct spoolss_EnumPrinterDrivers *r)
10269 {
10270         p->rng_fault_state = true;
10271         return WERR_NOT_SUPPORTED;
10272 }
10273
10274 /****************************************************************
10275  _spoolss_GetPrinterDriver
10276 ****************************************************************/
10277
10278 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10279                                  struct spoolss_GetPrinterDriver *r)
10280 {
10281         p->rng_fault_state = true;
10282         return WERR_NOT_SUPPORTED;
10283 }
10284
10285 /****************************************************************
10286  _spoolss_ReadPrinter
10287 ****************************************************************/
10288
10289 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10290                             struct spoolss_ReadPrinter *r)
10291 {
10292         p->rng_fault_state = true;
10293         return WERR_NOT_SUPPORTED;
10294 }
10295
10296 /****************************************************************
10297  _spoolss_GetPrinterData
10298 ****************************************************************/
10299
10300 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10301                                struct spoolss_GetPrinterData *r)
10302 {
10303         p->rng_fault_state = true;
10304         return WERR_NOT_SUPPORTED;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_SetPrinterData
10309 ****************************************************************/
10310
10311 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10312                                struct spoolss_SetPrinterData *r)
10313 {
10314         p->rng_fault_state = true;
10315         return WERR_NOT_SUPPORTED;
10316 }
10317
10318 /****************************************************************
10319  _spoolss_WaitForPrinterChange
10320 ****************************************************************/
10321
10322 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10323                                      struct spoolss_WaitForPrinterChange *r)
10324 {
10325         p->rng_fault_state = true;
10326         return WERR_NOT_SUPPORTED;
10327 }
10328
10329 /****************************************************************
10330  _spoolss_AddPort
10331 ****************************************************************/
10332
10333 WERROR _spoolss_AddPort(pipes_struct *p,
10334                         struct spoolss_AddPort *r)
10335 {
10336         p->rng_fault_state = true;
10337         return WERR_NOT_SUPPORTED;
10338 }
10339
10340 /****************************************************************
10341  _spoolss_ConfigurePort
10342 ****************************************************************/
10343
10344 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10345                               struct spoolss_ConfigurePort *r)
10346 {
10347         p->rng_fault_state = true;
10348         return WERR_NOT_SUPPORTED;
10349 }
10350
10351 /****************************************************************
10352  _spoolss_DeletePort
10353 ****************************************************************/
10354
10355 WERROR _spoolss_DeletePort(pipes_struct *p,
10356                            struct spoolss_DeletePort *r)
10357 {
10358         p->rng_fault_state = true;
10359         return WERR_NOT_SUPPORTED;
10360 }
10361
10362 /****************************************************************
10363  _spoolss_CreatePrinterIC
10364 ****************************************************************/
10365
10366 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10367                                 struct spoolss_CreatePrinterIC *r)
10368 {
10369         p->rng_fault_state = true;
10370         return WERR_NOT_SUPPORTED;
10371 }
10372
10373 /****************************************************************
10374  _spoolss_PlayGDIScriptOnPrinterIC
10375 ****************************************************************/
10376
10377 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10378                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10379 {
10380         p->rng_fault_state = true;
10381         return WERR_NOT_SUPPORTED;
10382 }
10383
10384 /****************************************************************
10385  _spoolss_DeletePrinterIC
10386 ****************************************************************/
10387
10388 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10389                                 struct spoolss_DeletePrinterIC *r)
10390 {
10391         p->rng_fault_state = true;
10392         return WERR_NOT_SUPPORTED;
10393 }
10394
10395 /****************************************************************
10396  _spoolss_AddPrinterConnection
10397 ****************************************************************/
10398
10399 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10400                                      struct spoolss_AddPrinterConnection *r)
10401 {
10402         p->rng_fault_state = true;
10403         return WERR_NOT_SUPPORTED;
10404 }
10405
10406 /****************************************************************
10407  _spoolss_DeletePrinterConnection
10408 ****************************************************************/
10409
10410 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10411                                         struct spoolss_DeletePrinterConnection *r)
10412 {
10413         p->rng_fault_state = true;
10414         return WERR_NOT_SUPPORTED;
10415 }
10416
10417 /****************************************************************
10418  _spoolss_PrinterMessageBox
10419 ****************************************************************/
10420
10421 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10422                                   struct spoolss_PrinterMessageBox *r)
10423 {
10424         p->rng_fault_state = true;
10425         return WERR_NOT_SUPPORTED;
10426 }
10427
10428 /****************************************************************
10429  _spoolss_AddMonitor
10430 ****************************************************************/
10431
10432 WERROR _spoolss_AddMonitor(pipes_struct *p,
10433                            struct spoolss_AddMonitor *r)
10434 {
10435         p->rng_fault_state = true;
10436         return WERR_NOT_SUPPORTED;
10437 }
10438
10439 /****************************************************************
10440  _spoolss_DeleteMonitor
10441 ****************************************************************/
10442
10443 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10444                               struct spoolss_DeleteMonitor *r)
10445 {
10446         p->rng_fault_state = true;
10447         return WERR_NOT_SUPPORTED;
10448 }
10449
10450 /****************************************************************
10451  _spoolss_DeletePrintProcessor
10452 ****************************************************************/
10453
10454 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10455                                      struct spoolss_DeletePrintProcessor *r)
10456 {
10457         p->rng_fault_state = true;
10458         return WERR_NOT_SUPPORTED;
10459 }
10460
10461 /****************************************************************
10462  _spoolss_AddPrintProvidor
10463 ****************************************************************/
10464
10465 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10466                                  struct spoolss_AddPrintProvidor *r)
10467 {
10468         p->rng_fault_state = true;
10469         return WERR_NOT_SUPPORTED;
10470 }
10471
10472 /****************************************************************
10473  _spoolss_DeletePrintProvidor
10474 ****************************************************************/
10475
10476 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10477                                     struct spoolss_DeletePrintProvidor *r)
10478 {
10479         p->rng_fault_state = true;
10480         return WERR_NOT_SUPPORTED;
10481 }
10482
10483 /****************************************************************
10484  _spoolss_GetPrinterDriver2
10485 ****************************************************************/
10486
10487 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10488                                   struct spoolss_GetPrinterDriver2 *r)
10489 {
10490         p->rng_fault_state = true;
10491         return WERR_NOT_SUPPORTED;
10492 }
10493
10494 /****************************************************************
10495  _spoolss_FindFirstPrinterChangeNotification
10496 ****************************************************************/
10497
10498 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10499                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10500 {
10501         p->rng_fault_state = true;
10502         return WERR_NOT_SUPPORTED;
10503 }
10504
10505 /****************************************************************
10506  _spoolss_FindNextPrinterChangeNotification
10507 ****************************************************************/
10508
10509 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10510                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10511 {
10512         p->rng_fault_state = true;
10513         return WERR_NOT_SUPPORTED;
10514 }
10515
10516 /****************************************************************
10517  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10518 ****************************************************************/
10519
10520 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10521                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10522 {
10523         p->rng_fault_state = true;
10524         return WERR_NOT_SUPPORTED;
10525 }
10526
10527 /****************************************************************
10528  _spoolss_ReplyOpenPrinter
10529 ****************************************************************/
10530
10531 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10532                                  struct spoolss_ReplyOpenPrinter *r)
10533 {
10534         p->rng_fault_state = true;
10535         return WERR_NOT_SUPPORTED;
10536 }
10537
10538 /****************************************************************
10539  _spoolss_RouterReplyPrinter
10540 ****************************************************************/
10541
10542 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10543                                    struct spoolss_RouterReplyPrinter *r)
10544 {
10545         p->rng_fault_state = true;
10546         return WERR_NOT_SUPPORTED;
10547 }
10548
10549 /****************************************************************
10550  _spoolss_ReplyClosePrinter
10551 ****************************************************************/
10552
10553 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10554                                   struct spoolss_ReplyClosePrinter *r)
10555 {
10556         p->rng_fault_state = true;
10557         return WERR_NOT_SUPPORTED;
10558 }
10559
10560 /****************************************************************
10561  _spoolss_AddPortEx
10562 ****************************************************************/
10563
10564 WERROR _spoolss_AddPortEx(pipes_struct *p,
10565                           struct spoolss_AddPortEx *r)
10566 {
10567         p->rng_fault_state = true;
10568         return WERR_NOT_SUPPORTED;
10569 }
10570
10571 /****************************************************************
10572  _spoolss_RouterFindFirstPrinterChangeNotification
10573 ****************************************************************/
10574
10575 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10576                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10577 {
10578         p->rng_fault_state = true;
10579         return WERR_NOT_SUPPORTED;
10580 }
10581
10582 /****************************************************************
10583  _spoolss_SpoolerInit
10584 ****************************************************************/
10585
10586 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10587                             struct spoolss_SpoolerInit *r)
10588 {
10589         p->rng_fault_state = true;
10590         return WERR_NOT_SUPPORTED;
10591 }
10592
10593 /****************************************************************
10594  _spoolss_ResetPrinterEx
10595 ****************************************************************/
10596
10597 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10598                                struct spoolss_ResetPrinterEx *r)
10599 {
10600         p->rng_fault_state = true;
10601         return WERR_NOT_SUPPORTED;
10602 }
10603
10604 /****************************************************************
10605  _spoolss_RouterReplyPrinterEx
10606 ****************************************************************/
10607
10608 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10609                                      struct spoolss_RouterReplyPrinterEx *r)
10610 {
10611         p->rng_fault_state = true;
10612         return WERR_NOT_SUPPORTED;
10613 }
10614
10615 /****************************************************************
10616  _spoolss_44
10617 ****************************************************************/
10618
10619 WERROR _spoolss_44(pipes_struct *p,
10620                    struct spoolss_44 *r)
10621 {
10622         p->rng_fault_state = true;
10623         return WERR_NOT_SUPPORTED;
10624 }
10625
10626 /****************************************************************
10627  _spoolss_47
10628 ****************************************************************/
10629
10630 WERROR _spoolss_47(pipes_struct *p,
10631                    struct spoolss_47 *r)
10632 {
10633         p->rng_fault_state = true;
10634         return WERR_NOT_SUPPORTED;
10635 }
10636
10637 /****************************************************************
10638  _spoolss_EnumPrinterData
10639 ****************************************************************/
10640
10641 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10642                                 struct spoolss_EnumPrinterData *r)
10643 {
10644         p->rng_fault_state = true;
10645         return WERR_NOT_SUPPORTED;
10646 }
10647
10648 /****************************************************************
10649  _spoolss_4a
10650 ****************************************************************/
10651
10652 WERROR _spoolss_4a(pipes_struct *p,
10653                    struct spoolss_4a *r)
10654 {
10655         p->rng_fault_state = true;
10656         return WERR_NOT_SUPPORTED;
10657 }
10658
10659 /****************************************************************
10660  _spoolss_4b
10661 ****************************************************************/
10662
10663 WERROR _spoolss_4b(pipes_struct *p,
10664                    struct spoolss_4b *r)
10665 {
10666         p->rng_fault_state = true;
10667         return WERR_NOT_SUPPORTED;
10668 }
10669
10670 /****************************************************************
10671  _spoolss_4c
10672 ****************************************************************/
10673
10674 WERROR _spoolss_4c(pipes_struct *p,
10675                    struct spoolss_4c *r)
10676 {
10677         p->rng_fault_state = true;
10678         return WERR_NOT_SUPPORTED;
10679 }
10680
10681 /****************************************************************
10682  _spoolss_EnumPrinterDataEx
10683 ****************************************************************/
10684
10685 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10686                                   struct spoolss_EnumPrinterDataEx *r)
10687 {
10688         p->rng_fault_state = true;
10689         return WERR_NOT_SUPPORTED;
10690 }
10691
10692 /****************************************************************
10693  _spoolss_EnumPrinterKey
10694 ****************************************************************/
10695
10696 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10697                                struct spoolss_EnumPrinterKey *r)
10698 {
10699         p->rng_fault_state = true;
10700         return WERR_NOT_SUPPORTED;
10701 }
10702
10703 /****************************************************************
10704  _spoolss_53
10705 ****************************************************************/
10706
10707 WERROR _spoolss_53(pipes_struct *p,
10708                    struct spoolss_53 *r)
10709 {
10710         p->rng_fault_state = true;
10711         return WERR_NOT_SUPPORTED;
10712 }
10713
10714 /****************************************************************
10715  _spoolss_55
10716 ****************************************************************/
10717
10718 WERROR _spoolss_55(pipes_struct *p,
10719                    struct spoolss_55 *r)
10720 {
10721         p->rng_fault_state = true;
10722         return WERR_NOT_SUPPORTED;
10723 }
10724
10725 /****************************************************************
10726  _spoolss_56
10727 ****************************************************************/
10728
10729 WERROR _spoolss_56(pipes_struct *p,
10730                    struct spoolss_56 *r)
10731 {
10732         p->rng_fault_state = true;
10733         return WERR_NOT_SUPPORTED;
10734 }
10735
10736 /****************************************************************
10737  _spoolss_57
10738 ****************************************************************/
10739
10740 WERROR _spoolss_57(pipes_struct *p,
10741                    struct spoolss_57 *r)
10742 {
10743         p->rng_fault_state = true;
10744         return WERR_NOT_SUPPORTED;
10745 }
10746
10747 /****************************************************************
10748  _spoolss_5a
10749 ****************************************************************/
10750
10751 WERROR _spoolss_5a(pipes_struct *p,
10752                    struct spoolss_5a *r)
10753 {
10754         p->rng_fault_state = true;
10755         return WERR_NOT_SUPPORTED;
10756 }
10757
10758 /****************************************************************
10759  _spoolss_5b
10760 ****************************************************************/
10761
10762 WERROR _spoolss_5b(pipes_struct *p,
10763                    struct spoolss_5b *r)
10764 {
10765         p->rng_fault_state = true;
10766         return WERR_NOT_SUPPORTED;
10767 }
10768
10769 /****************************************************************
10770  _spoolss_5c
10771 ****************************************************************/
10772
10773 WERROR _spoolss_5c(pipes_struct *p,
10774                    struct spoolss_5c *r)
10775 {
10776         p->rng_fault_state = true;
10777         return WERR_NOT_SUPPORTED;
10778 }
10779
10780 /****************************************************************
10781  _spoolss_5d
10782 ****************************************************************/
10783
10784 WERROR _spoolss_5d(pipes_struct *p,
10785                    struct spoolss_5d *r)
10786 {
10787         p->rng_fault_state = true;
10788         return WERR_NOT_SUPPORTED;
10789 }
10790
10791 /****************************************************************
10792  _spoolss_5e
10793 ****************************************************************/
10794
10795 WERROR _spoolss_5e(pipes_struct *p,
10796                    struct spoolss_5e *r)
10797 {
10798         p->rng_fault_state = true;
10799         return WERR_NOT_SUPPORTED;
10800 }
10801
10802 /****************************************************************
10803  _spoolss_5f
10804 ****************************************************************/
10805
10806 WERROR _spoolss_5f(pipes_struct *p,
10807                    struct spoolss_5f *r)
10808 {
10809         p->rng_fault_state = true;
10810         return WERR_NOT_SUPPORTED;
10811 }
10812