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