s3-spoolss: use pidl for _spoolss_GetPrinterData.
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32         ((info)?ndr_size_##fn(info, level, ic, 0):0)
33
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
36
37 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
38
39
40 extern userdom_struct current_user_info;
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_RPC_SRV
44
45 #ifndef MAX_OPEN_PRINTER_EXS
46 #define MAX_OPEN_PRINTER_EXS 50
47 #endif
48
49 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
50 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
51
52 struct table_node {
53         const char    *long_archi;
54         const char    *short_archi;
55         int     version;
56 };
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32 counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32 smb_connections=0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected==True) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected=False;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
231 {
232         Printer_entry *find_printer = NULL;
233
234         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
235                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
236                 return NULL;
237         }
238
239         return find_printer;
240 }
241
242 /****************************************************************************
243  Close printer index by handle.
244 ****************************************************************************/
245
246 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
247 {
248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249
250         if (!Printer) {
251                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
252                 return False;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return True;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
265 {
266         char *cmd = lp_deleteprinter_cmd();
267         char *command = NULL;
268         int ret;
269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
270         bool is_print_op = False;
271
272         /* can't fail if we don't try */
273
274         if ( !*cmd )
275                 return WERR_OK;
276
277         command = talloc_asprintf(ctx,
278                         "%s \"%s\"",
279                         cmd, sharename);
280         if (!command) {
281                 return WERR_NOMEM;
282         }
283         if ( token )
284                 is_print_op = user_has_privileges( token, &se_printop );
285
286         DEBUG(10,("Running [%s]\n", command));
287
288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290         if ( is_print_op )
291                 become_root();
292
293         if ( (ret = smbrun(command, NULL)) == 0 ) {
294                 /* Tell everyone we updated smb.conf. */
295                 message_send_all(smbd_messaging_context(),
296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
297         }
298
299         if ( is_print_op )
300                 unbecome_root();
301
302         /********** END SePrintOperatorPrivlege BLOCK **********/
303
304         DEBUGADD(10,("returned [%d]\n", ret));
305
306         TALLOC_FREE(command);
307
308         if (ret != 0)
309                 return WERR_BADFID; /* What to return here? */
310
311         /* go ahead and re-read the services immediately */
312         reload_services( False );
313
314         if ( lp_servicenumber( sharename )  < 0 )
315                 return WERR_ACCESS_DENIED;
316
317         return WERR_OK;
318 }
319
320 /****************************************************************************
321  Delete a printer given a handle.
322 ****************************************************************************/
323
324 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
325 {
326         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
327
328         if (!Printer) {
329                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
330                 return WERR_BADFID;
331         }
332
333         /*
334          * It turns out that Windows allows delete printer on a handle
335          * opened by an admin user, then used on a pipe handle created
336          * by an anonymous user..... but they're working on security.... riiight !
337          * JRA.
338          */
339
340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
341                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
342                 return WERR_ACCESS_DENIED;
343         }
344
345         /* this does not need a become root since the access check has been
346            done on the handle already */
347
348         if (del_a_printer( Printer->sharename ) != 0) {
349                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
350                 return WERR_BADFID;
351         }
352
353         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
354                                    Printer->sharename );
355 }
356
357 /****************************************************************************
358  Return the snum of a printer corresponding to an handle.
359 ****************************************************************************/
360
361 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
362                              struct share_params **params)
363 {
364         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368                 return False;
369         }
370
371         switch (Printer->printer_type) {
372                 case SPLHND_PRINTER:
373                         DEBUG(4,("short name:%s\n", Printer->sharename));
374                         *number = print_queue_snum(Printer->sharename);
375                         return (*number != -1);
376                 case SPLHND_SERVER:
377                         return False;
378                 default:
379                         return False;
380         }
381 }
382
383 /****************************************************************************
384  Set printer handle type.
385  Check if it's \\server or \\server\printer
386 ****************************************************************************/
387
388 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
389 {
390         DEBUG(3,("Setting printer type=%s\n", handlename));
391
392         if ( strlen(handlename) < 3 ) {
393                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
394                 return False;
395         }
396
397         /* it's a print server */
398         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
399                 DEBUGADD(4,("Printer is a print server\n"));
400                 Printer->printer_type = SPLHND_SERVER;
401         }
402         /* it's a printer (set_printer_hnd_name() will handle port monitors */
403         else {
404                 DEBUGADD(4,("Printer is a printer\n"));
405                 Printer->printer_type = SPLHND_PRINTER;
406         }
407
408         return True;
409 }
410
411 /****************************************************************************
412  Set printer handle name..  Accept names like \\server, \\server\printer,
413  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
414  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
415  XcvDataPort() interface.
416 ****************************************************************************/
417
418 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
419 {
420         int snum;
421         int n_services=lp_numservices();
422         char *aprinter, *printername;
423         const char *servername;
424         fstring sname;
425         bool found=False;
426         NT_PRINTER_INFO_LEVEL *printer = NULL;
427         WERROR result;
428
429         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
430
431         aprinter = handlename;
432         if ( *handlename == '\\' ) {
433                 servername = canon_servername(handlename);
434                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
435                         *aprinter = '\0';
436                         aprinter++;
437                 }
438         } else {
439                 servername = "";
440         }
441
442         /* save the servername to fill in replies on this handle */
443
444         if ( !is_myname_or_ipaddr( servername ) )
445                 return False;
446
447         fstrcpy( Printer->servername, servername );
448
449         if ( Printer->printer_type == SPLHND_SERVER )
450                 return True;
451
452         if ( Printer->printer_type != SPLHND_PRINTER )
453                 return False;
454
455         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
456
457         /* check for the Port Monitor Interface */
458
459         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
460                 Printer->printer_type = SPLHND_PORTMON_TCP;
461                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
462                 found = True;
463         }
464         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
465                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
466                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
467                 found = True;
468         }
469
470         /* Search all sharenames first as this is easier than pulling
471            the printer_info_2 off of disk. Don't use find_service() since
472            that calls out to map_username() */
473
474         /* do another loop to look for printernames */
475
476         for (snum=0; !found && snum<n_services; snum++) {
477
478                 /* no point going on if this is not a printer */
479
480                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
481                         continue;
482
483                 fstrcpy(sname, lp_servicename(snum));
484                 if ( strequal( aprinter, sname ) ) {
485                         found = True;
486                         break;
487                 }
488
489                 /* no point looking up the printer object if
490                    we aren't allowing printername != sharename */
491
492                 if ( lp_force_printername(snum) )
493                         continue;
494
495                 fstrcpy(sname, lp_servicename(snum));
496
497                 printer = NULL;
498
499                 /* This call doesn't fill in the location or comment from
500                  * a CUPS server for efficiency with large numbers of printers.
501                  * JRA.
502                  */
503
504                 result = get_a_printer_search( NULL, &printer, 2, sname );
505                 if ( !W_ERROR_IS_OK(result) ) {
506                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
507                                 sname, win_errstr(result)));
508                         continue;
509                 }
510
511                 /* printername is always returned as \\server\printername */
512                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
513                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
514                                 printer->info_2->printername));
515                         free_a_printer( &printer, 2);
516                         continue;
517                 }
518
519                 printername++;
520
521                 if ( strequal(printername, aprinter) ) {
522                         free_a_printer( &printer, 2);
523                         found = True;
524                         break;
525                 }
526
527                 DEBUGADD(10, ("printername: %s\n", printername));
528
529                 free_a_printer( &printer, 2);
530         }
531
532         free_a_printer( &printer, 2);
533
534         if ( !found ) {
535                 DEBUGADD(4,("Printer not found\n"));
536                 return False;
537         }
538
539         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
540
541         fstrcpy(Printer->sharename, sname);
542
543         return True;
544 }
545
546 /****************************************************************************
547  Find first available printer slot. creates a printer handle for you.
548  ****************************************************************************/
549
550 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
551 {
552         Printer_entry *new_printer;
553
554         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
555
556         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
557         if (new_printer == NULL) {
558                 return false;
559         }
560         talloc_set_destructor(new_printer, printer_entry_destructor);
561
562         if (!create_policy_hnd(p, hnd, new_printer)) {
563                 TALLOC_FREE(new_printer);
564                 return False;
565         }
566
567         /* Add to the internal list. */
568         DLIST_ADD(printers_list, new_printer);
569
570         new_printer->notify.option=NULL;
571
572         if (!set_printer_hnd_printertype(new_printer, name)) {
573                 close_printer_handle(p, hnd);
574                 return False;
575         }
576
577         if (!set_printer_hnd_name(new_printer, name)) {
578                 close_printer_handle(p, hnd);
579                 return False;
580         }
581
582         new_printer->access_granted = access_granted;
583
584         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585
586         return True;
587 }
588
589 /***************************************************************************
590  check to see if the client motify handle is monitoring the notification
591  given by (notify_type, notify_field).
592  **************************************************************************/
593
594 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
595                                       uint16 notify_field)
596 {
597         return True;
598 }
599
600 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
601                                 uint16 notify_field)
602 {
603         struct spoolss_NotifyOption *option = p->notify.option;
604         uint32 i, j;
605
606         /*
607          * Flags should always be zero when the change notify
608          * is registered by the client's spooler.  A user Win32 app
609          * might use the flags though instead of the NOTIFY_OPTION_INFO
610          * --jerry
611          */
612
613         if (!option) {
614                 return False;
615         }
616
617         if (p->notify.flags)
618                 return is_monitoring_event_flags(
619                         p->notify.flags, notify_type, notify_field);
620
621         for (i = 0; i < option->count; i++) {
622
623                 /* Check match for notify_type */
624
625                 if (option->types[i].type != notify_type)
626                         continue;
627
628                 /* Check match for field */
629
630                 for (j = 0; j < option->types[i].count; j++) {
631                         if (option->types[i].fields[j] == notify_field) {
632                                 return True;
633                         }
634                 }
635         }
636
637         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
638                    p->servername, p->sharename, notify_type, notify_field));
639
640         return False;
641 }
642
643 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
644         _data->data.integer[0] = _integer; \
645         _data->data.integer[1] = 0;
646
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
649         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
650         if (!_data->data.string.string) {\
651                 _data->data.string.size = 0; \
652         } \
653         _data->data.string.size = strlen_m_term(_p) * 2;
654
655 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
656         _data->data.devmode.devmode = _devmode;
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
659         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
660         if (!_data->data.sd.sd) { \
661                 _data->data.sd.sd_size = 0; \
662         } \
663         _data->data.sd.sd_size = _size;
664
665 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
666                                    struct tm *t,
667                                    const char **pp,
668                                    uint32_t *plen)
669 {
670         struct spoolss_Time st;
671         uint32_t len = 16;
672         char *p;
673
674         if (!init_systemtime(&st, t)) {
675                 return;
676         }
677
678         p = talloc_array(mem_ctx, char, len);
679         if (!p) {
680                 return;
681         }
682
683         /*
684          * Systemtime must be linearized as a set of UINT16's.
685          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
686          */
687
688         SSVAL(p, 0, st.year);
689         SSVAL(p, 2, st.month);
690         SSVAL(p, 4, st.day_of_week);
691         SSVAL(p, 6, st.day);
692         SSVAL(p, 8, st.hour);
693         SSVAL(p, 10, st.minute);
694         SSVAL(p, 12, st.second);
695         SSVAL(p, 14, st.millisecond);
696
697         *pp = p;
698         *plen = len;
699 }
700
701 /* Convert a notification message to a struct spoolss_Notify */
702
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704                              struct spoolss_Notify *data,
705                              TALLOC_CTX *mem_ctx)
706 {
707         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
708 }
709
710 static void notify_string(struct spoolss_notify_msg *msg,
711                           struct spoolss_Notify *data,
712                           TALLOC_CTX *mem_ctx)
713 {
714         /* The length of the message includes the trailing \0 */
715
716         data->data.string.size = msg->len * 2;
717         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
718         if (!data->data.string.string) {
719                 data->data.string.size = 0;
720                 return;
721         }
722 }
723
724 static void notify_system_time(struct spoolss_notify_msg *msg,
725                                struct spoolss_Notify *data,
726                                TALLOC_CTX *mem_ctx)
727 {
728         data->data.string.string = NULL;
729         data->data.string.size = 0;
730
731         if (msg->len != sizeof(time_t)) {
732                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
733                           msg->len));
734                 return;
735         }
736
737         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
738                                &data->data.string.string,
739                                &data->data.string.size);
740 }
741
742 struct notify2_message_table {
743         const char *name;
744         void (*fn)(struct spoolss_notify_msg *msg,
745                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
746 };
747
748 static struct notify2_message_table printer_notify_table[] = {
749         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
750         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
751         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
752         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
753         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
754         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
755         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
756         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
757         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
758         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
759         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
760         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
761         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
762         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
763         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
764         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
765         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
766         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
767         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 };
769
770 static struct notify2_message_table job_notify_table[] = {
771         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
772         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
773         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
774         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
775         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
776         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
777         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
778         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
779         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
780         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
781         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
782         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
783         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
784         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
785         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
786         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
787         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
788         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
789         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
790         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
791         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
792         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
793         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
794         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
795 };
796
797
798 /***********************************************************************
799  Allocate talloc context for container object
800  **********************************************************************/
801
802 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 {
804         if ( !ctr )
805                 return;
806
807         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808
809         return;
810 }
811
812 /***********************************************************************
813  release all allocated memory and zero out structure
814  **********************************************************************/
815
816 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
817 {
818         if ( !ctr )
819                 return;
820
821         if ( ctr->ctx )
822                 talloc_destroy(ctr->ctx);
823
824         ZERO_STRUCTP(ctr);
825
826         return;
827 }
828
829 /***********************************************************************
830  **********************************************************************/
831
832 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 {
834         if ( !ctr )
835                 return NULL;
836
837         return ctr->ctx;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 {
845         if ( !ctr || !ctr->msg_groups )
846                 return NULL;
847
848         if ( idx >= ctr->num_groups )
849                 return NULL;
850
851         return &ctr->msg_groups[idx];
852
853 }
854
855 /***********************************************************************
856  How many groups of change messages do we have ?
857  **********************************************************************/
858
859 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 {
861         if ( !ctr )
862                 return 0;
863
864         return ctr->num_groups;
865 }
866
867 /***********************************************************************
868  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
869  **********************************************************************/
870
871 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 {
873         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
874         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
875         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
876         int                             i, new_slot;
877
878         if ( !ctr || !msg )
879                 return 0;
880
881         /* loop over all groups looking for a matching printer name */
882
883         for ( i=0; i<ctr->num_groups; i++ ) {
884                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
885                         break;
886         }
887
888         /* add a new group? */
889
890         if ( i == ctr->num_groups ) {
891                 ctr->num_groups++;
892
893                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
894                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895                         return 0;
896                 }
897                 ctr->msg_groups = groups;
898
899                 /* clear the new entry and set the printer name */
900
901                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
902                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903         }
904
905         /* add the change messages; 'i' is the correct index now regardless */
906
907         msg_grp = &ctr->msg_groups[i];
908
909         msg_grp->num_msgs++;
910
911         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
912                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913                 return 0;
914         }
915         msg_grp->msgs = msg_list;
916
917         new_slot = msg_grp->num_msgs-1;
918         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919
920         /* need to allocate own copy of data */
921
922         if ( msg->len != 0 )
923                 msg_grp->msgs[new_slot].notify.data = (char *)
924                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
925
926         return ctr->num_groups;
927 }
928
929 /***********************************************************************
930  Send a change notication message on all handles which have a call
931  back registered
932  **********************************************************************/
933
934 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
935 {
936         Printer_entry            *p;
937         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
938         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
939         SPOOLSS_NOTIFY_MSG       *messages;
940         int                      sending_msg_count;
941
942         if ( !msg_group ) {
943                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944                 return;
945         }
946
947         messages = msg_group->msgs;
948
949         if ( !messages ) {
950                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951                 return;
952         }
953
954         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
955
956         /* loop over all printers */
957
958         for (p = printers_list; p; p = p->next) {
959                 struct spoolss_Notify *notifies;
960                 uint32_t count = 0;
961                 uint32_t id;
962                 int     i;
963
964                 /* Is there notification on this handle? */
965
966                 if ( !p->notify.client_connected )
967                         continue;
968
969                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
970
971                 /* For this printer?  Print servers always receive
972                    notifications. */
973
974                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
975                     ( !strequal(msg_group->printername, p->sharename) ) )
976                         continue;
977
978                 DEBUG(10,("Our printer\n"));
979
980                 /* allocate the max entries possible */
981
982                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
983                 if (!notifies) {
984                         return;
985                 }
986
987                 /* build the array of change notifications */
988
989                 sending_msg_count = 0;
990
991                 for ( i=0; i<msg_group->num_msgs; i++ ) {
992                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
993
994                         /* Are we monitoring this event? */
995
996                         if (!is_monitoring_event(p, msg->type, msg->field))
997                                 continue;
998
999                         sending_msg_count++;
1000
1001
1002                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1003                                 msg->type, msg->field, p->sharename));
1004
1005                         /*
1006                          * if the is a printer notification handle and not a job notification
1007                          * type, then set the id to 0.  Other wise just use what was specified
1008                          * in the message.
1009                          *
1010                          * When registering change notification on a print server handle
1011                          * we always need to send back the id (snum) matching the printer
1012                          * for which the change took place.  For change notify registered
1013                          * on a printer handle, this does not matter and the id should be 0.
1014                          *
1015                          * --jerry
1016                          */
1017
1018                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019                                 id = 0;
1020                         else
1021                                 id = msg->id;
1022
1023
1024                         /* Convert unix jobid to smb jobid */
1025
1026                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1027                                 id = sysjob_to_jobid(msg->id);
1028
1029                                 if (id == -1) {
1030                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1031                                         goto done;
1032                                 }
1033                         }
1034
1035                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1036
1037                         switch(msg->type) {
1038                         case PRINTER_NOTIFY_TYPE:
1039                                 if ( printer_notify_table[msg->field].fn )
1040                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1041                                 break;
1042
1043                         case JOB_NOTIFY_TYPE:
1044                                 if ( job_notify_table[msg->field].fn )
1045                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1046                                 break;
1047
1048                         default:
1049                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1050                                 goto done;
1051                         }
1052
1053                         count++;
1054                 }
1055
1056                 if ( sending_msg_count ) {
1057                         NTSTATUS status;
1058                         WERROR werr;
1059                         union spoolss_ReplyPrinterInfo info;
1060                         struct spoolss_NotifyInfo info0;
1061                         uint32_t reply_result;
1062
1063                         info0.version   = 0x2;
1064                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1065                         info0.count     = count;
1066                         info0.notifies  = notifies;
1067
1068                         info.info0 = &info0;
1069
1070                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1071                                                                      &p->notify.client_hnd,
1072                                                                      p->notify.change, /* color */
1073                                                                      p->notify.flags,
1074                                                                      &reply_result,
1075                                                                      0, /* reply_type, must be 0 */
1076                                                                      info,
1077                                                                      &werr);
1078                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1079                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1080                                         notify_cli_pipe->srv_name_slash,
1081                                         win_errstr(werr)));
1082                         }
1083                         switch (reply_result) {
1084                                 case 0:
1085                                         break;
1086                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1087                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1088                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1089                                         break;
1090                                 default:
1091                                         break;
1092                         }
1093                 }
1094         }
1095
1096 done:
1097         DEBUG(8,("send_notify2_changes: Exit...\n"));
1098         return;
1099 }
1100
1101 /***********************************************************************
1102  **********************************************************************/
1103
1104 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1105 {
1106
1107         uint32 tv_sec, tv_usec;
1108         size_t offset = 0;
1109
1110         /* Unpack message */
1111
1112         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1113                              msg->printer);
1114
1115         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1116                                 &tv_sec, &tv_usec,
1117                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1118
1119         if (msg->len == 0)
1120                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1121                            &msg->notify.value[0], &msg->notify.value[1]);
1122         else
1123                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1124                            &msg->len, &msg->notify.data);
1125
1126         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1127                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1128
1129         tv->tv_sec = tv_sec;
1130         tv->tv_usec = tv_usec;
1131
1132         if (msg->len == 0)
1133                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1134                           msg->notify.value[1]));
1135         else
1136                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1137
1138         return True;
1139 }
1140
1141 /********************************************************************
1142  Receive a notify2 message list
1143  ********************************************************************/
1144
1145 static void receive_notify2_message_list(struct messaging_context *msg,
1146                                          void *private_data,
1147                                          uint32_t msg_type,
1148                                          struct server_id server_id,
1149                                          DATA_BLOB *data)
1150 {
1151         size_t                  msg_count, i;
1152         char                    *buf = (char *)data->data;
1153         char                    *msg_ptr;
1154         size_t                  msg_len;
1155         SPOOLSS_NOTIFY_MSG      notify;
1156         SPOOLSS_NOTIFY_MSG_CTR  messages;
1157         int                     num_groups;
1158
1159         if (data->length < 4) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1161                 return;
1162         }
1163
1164         msg_count = IVAL(buf, 0);
1165         msg_ptr = buf + 4;
1166
1167         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168
1169         if (msg_count == 0) {
1170                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1171                 return;
1172         }
1173
1174         /* initialize the container */
1175
1176         ZERO_STRUCT( messages );
1177         notify_msg_ctr_init( &messages );
1178
1179         /*
1180          * build message groups for each printer identified
1181          * in a change_notify msg.  Remember that a PCN message
1182          * includes the handle returned for the srv_spoolss_replyopenprinter()
1183          * call.  Therefore messages are grouped according to printer handle.
1184          */
1185
1186         for ( i=0; i<msg_count; i++ ) {
1187                 struct timeval msg_tv;
1188
1189                 if (msg_ptr + 4 - buf > data->length) {
1190                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1191                         return;
1192                 }
1193
1194                 msg_len = IVAL(msg_ptr,0);
1195                 msg_ptr += 4;
1196
1197                 if (msg_ptr + msg_len - buf > data->length) {
1198                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1199                         return;
1200                 }
1201
1202                 /* unpack messages */
1203
1204                 ZERO_STRUCT( notify );
1205                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1206                 msg_ptr += msg_len;
1207
1208                 /* add to correct list in container */
1209
1210                 notify_msg_ctr_addmsg( &messages, &notify );
1211
1212                 /* free memory that might have been allocated by notify2_unpack_msg() */
1213
1214                 if ( notify.len != 0 )
1215                         SAFE_FREE( notify.notify.data );
1216         }
1217
1218         /* process each group of messages */
1219
1220         num_groups = notify_msg_ctr_numgroups( &messages );
1221         for ( i=0; i<num_groups; i++ )
1222                 send_notify2_changes( &messages, i );
1223
1224
1225         /* cleanup */
1226
1227         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228
1229         notify_msg_ctr_destroy( &messages );
1230
1231         return;
1232 }
1233
1234 /********************************************************************
1235  Send a message to ourself about new driver being installed
1236  so we can upgrade the information for each printer bound to this
1237  driver
1238  ********************************************************************/
1239
1240 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1241 {
1242         int len = strlen(drivername);
1243
1244         if (!len)
1245                 return False;
1246
1247         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1248                 drivername));
1249
1250         messaging_send_buf(smbd_messaging_context(), procid_self(),
1251                            MSG_PRINTER_DRVUPGRADE,
1252                            (uint8 *)drivername, len+1);
1253
1254         return True;
1255 }
1256
1257 /**********************************************************************
1258  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1259  over all printers, upgrading ones as necessary
1260  **********************************************************************/
1261
1262 void do_drv_upgrade_printer(struct messaging_context *msg,
1263                             void *private_data,
1264                             uint32_t msg_type,
1265                             struct server_id server_id,
1266                             DATA_BLOB *data)
1267 {
1268         fstring drivername;
1269         int snum;
1270         int n_services = lp_numservices();
1271         size_t len;
1272
1273         len = MIN(data->length,sizeof(drivername)-1);
1274         strncpy(drivername, (const char *)data->data, len);
1275
1276         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1277
1278         /* Iterate the printer list */
1279
1280         for (snum=0; snum<n_services; snum++)
1281         {
1282                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1283                 {
1284                         WERROR result;
1285                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1286
1287                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1288                         if (!W_ERROR_IS_OK(result))
1289                                 continue;
1290
1291                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1292                         {
1293                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1294
1295                                 /* all we care about currently is the change_id */
1296
1297                                 result = mod_a_printer(printer, 2);
1298                                 if (!W_ERROR_IS_OK(result)) {
1299                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1300                                                 win_errstr(result)));
1301                                 }
1302                         }
1303
1304                         free_a_printer(&printer, 2);
1305                 }
1306         }
1307
1308         /* all done */
1309 }
1310
1311 /********************************************************************
1312  Update the cache for all printq's with a registered client
1313  connection
1314  ********************************************************************/
1315
1316 void update_monitored_printq_cache( void )
1317 {
1318         Printer_entry *printer = printers_list;
1319         int snum;
1320
1321         /* loop through all printers and update the cache where
1322            client_connected == True */
1323         while ( printer )
1324         {
1325                 if ( (printer->printer_type == SPLHND_PRINTER)
1326                         && printer->notify.client_connected )
1327                 {
1328                         snum = print_queue_snum(printer->sharename);
1329                         print_queue_status( snum, NULL, NULL );
1330                 }
1331
1332                 printer = printer->next;
1333         }
1334
1335         return;
1336 }
1337 /********************************************************************
1338  Send a message to ourself about new driver being installed
1339  so we can upgrade the information for each printer bound to this
1340  driver
1341  ********************************************************************/
1342
1343 static bool srv_spoolss_reset_printerdata(char* drivername)
1344 {
1345         int len = strlen(drivername);
1346
1347         if (!len)
1348                 return False;
1349
1350         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351                 drivername));
1352
1353         messaging_send_buf(smbd_messaging_context(), procid_self(),
1354                            MSG_PRINTERDATA_INIT_RESET,
1355                            (uint8 *)drivername, len+1);
1356
1357         return True;
1358 }
1359
1360 /**********************************************************************
1361  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1362  over all printers, resetting printer data as neessary
1363  **********************************************************************/
1364
1365 void reset_all_printerdata(struct messaging_context *msg,
1366                            void *private_data,
1367                            uint32_t msg_type,
1368                            struct server_id server_id,
1369                            DATA_BLOB *data)
1370 {
1371         fstring drivername;
1372         int snum;
1373         int n_services = lp_numservices();
1374         size_t len;
1375
1376         len = MIN( data->length, sizeof(drivername)-1 );
1377         strncpy( drivername, (const char *)data->data, len );
1378
1379         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1380
1381         /* Iterate the printer list */
1382
1383         for ( snum=0; snum<n_services; snum++ )
1384         {
1385                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1386                 {
1387                         WERROR result;
1388                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1389
1390                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1391                         if ( !W_ERROR_IS_OK(result) )
1392                                 continue;
1393
1394                         /*
1395                          * if the printer is bound to the driver,
1396                          * then reset to the new driver initdata
1397                          */
1398
1399                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1400                         {
1401                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1402
1403                                 if ( !set_driver_init(printer, 2) ) {
1404                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1405                                                 printer->info_2->printername, printer->info_2->drivername));
1406                                 }
1407
1408                                 result = mod_a_printer( printer, 2 );
1409                                 if ( !W_ERROR_IS_OK(result) ) {
1410                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1411                                                 get_dos_error_msg(result)));
1412                                 }
1413                         }
1414
1415                         free_a_printer( &printer, 2 );
1416                 }
1417         }
1418
1419         /* all done */
1420
1421         return;
1422 }
1423
1424 /****************************************************************
1425  _spoolss_OpenPrinter
1426 ****************************************************************/
1427
1428 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1429                             struct spoolss_OpenPrinter *r)
1430 {
1431         struct spoolss_OpenPrinterEx e;
1432         WERROR werr;
1433
1434         ZERO_STRUCT(e.in.userlevel);
1435
1436         e.in.printername        = r->in.printername;
1437         e.in.datatype           = r->in.datatype;
1438         e.in.devmode_ctr        = r->in.devmode_ctr;
1439         e.in.access_mask        = r->in.access_mask;
1440         e.in.level              = 0;
1441
1442         e.out.handle            = r->out.handle;
1443
1444         werr = _spoolss_OpenPrinterEx(p, &e);
1445
1446         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1447                 /* OpenPrinterEx returns this for a bad
1448                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1449                  * instead.
1450                  */
1451                 werr = WERR_INVALID_PRINTER_NAME;
1452         }
1453
1454         return werr;
1455 }
1456
1457 /********************************************************************
1458  FIXME: temporary convert_devicemode_new function
1459  ********************************************************************/
1460
1461 static bool convert_devicemode_new(const char *printername,
1462                                    struct spoolss_DeviceMode *devmode,
1463                                    NT_DEVICEMODE **pp_nt_devmode)
1464 {
1465         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1466
1467         /*
1468          * Ensure nt_devmode is a valid pointer
1469          * as we will be overwriting it.
1470          */
1471
1472         if (nt_devmode == NULL) {
1473                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1474                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1475                         return false;
1476         }
1477
1478         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1479         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1480
1481         nt_devmode->specversion         = devmode->specversion;
1482         nt_devmode->driverversion       = devmode->driverversion;
1483         nt_devmode->size                = devmode->size;
1484         nt_devmode->fields              = devmode->fields;
1485         nt_devmode->orientation         = devmode->orientation;
1486         nt_devmode->papersize           = devmode->papersize;
1487         nt_devmode->paperlength         = devmode->paperlength;
1488         nt_devmode->paperwidth          = devmode->paperwidth;
1489         nt_devmode->scale               = devmode->scale;
1490         nt_devmode->copies              = devmode->copies;
1491         nt_devmode->defaultsource       = devmode->defaultsource;
1492         nt_devmode->printquality        = devmode->printquality;
1493         nt_devmode->color               = devmode->color;
1494         nt_devmode->duplex              = devmode->duplex;
1495         nt_devmode->yresolution         = devmode->yresolution;
1496         nt_devmode->ttoption            = devmode->ttoption;
1497         nt_devmode->collate             = devmode->collate;
1498
1499         nt_devmode->logpixels           = devmode->logpixels;
1500         nt_devmode->bitsperpel          = devmode->bitsperpel;
1501         nt_devmode->pelswidth           = devmode->pelswidth;
1502         nt_devmode->pelsheight          = devmode->pelsheight;
1503         nt_devmode->displayflags        = devmode->displayflags;
1504         nt_devmode->displayfrequency    = devmode->displayfrequency;
1505         nt_devmode->icmmethod           = devmode->icmmethod;
1506         nt_devmode->icmintent           = devmode->icmintent;
1507         nt_devmode->mediatype           = devmode->mediatype;
1508         nt_devmode->dithertype          = devmode->dithertype;
1509         nt_devmode->reserved1           = devmode->reserved1;
1510         nt_devmode->reserved2           = devmode->reserved2;
1511         nt_devmode->panningwidth        = devmode->panningwidth;
1512         nt_devmode->panningheight       = devmode->panningheight;
1513
1514         /*
1515          * Only change private and driverextra if the incoming devmode
1516          * has a new one. JRA.
1517          */
1518
1519         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1520                 SAFE_FREE(nt_devmode->nt_dev_private);
1521                 nt_devmode->driverextra = devmode->__driverextra_length;
1522                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1523                         return false;
1524                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1525         }
1526
1527         *pp_nt_devmode = nt_devmode;
1528
1529         return true;
1530 }
1531
1532 /****************************************************************
1533  _spoolss_OpenPrinterEx
1534 ****************************************************************/
1535
1536 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1537                               struct spoolss_OpenPrinterEx *r)
1538 {
1539         POLICY_HND              *handle = r->out.handle;
1540         char *name = CONST_DISCARD(char *, r->in.printername);
1541         int snum;
1542         Printer_entry *Printer=NULL;
1543
1544         if (!name) {
1545                 return WERR_INVALID_PARAM;
1546         }
1547
1548         /* some sanity check because you can open a printer or a print server */
1549         /* aka: \\server\printer or \\server */
1550
1551         DEBUGADD(3,("checking name: %s\n",name));
1552
1553         if (!open_printer_hnd(p, handle, name, 0)) {
1554                 ZERO_STRUCTP(r->out.handle);
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         Printer=find_printer_index_by_hnd(p, handle);
1559         if ( !Printer ) {
1560                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1561                         "handle we created for printer %s\n", name ));
1562                 close_printer_handle(p,handle);
1563                 ZERO_STRUCTP(r->out.handle);
1564                 return WERR_INVALID_PARAM;
1565         }
1566
1567         /*
1568          * First case: the user is opening the print server:
1569          *
1570          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1571          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1572          *
1573          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1574          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1575          * or if the user is listed in the smb.conf printer admin parameter.
1576          *
1577          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1578          * client view printer folder, but does not show the MSAPW.
1579          *
1580          * Note: this test needs code to check access rights here too. Jeremy
1581          * could you look at this?
1582          *
1583          * Second case: the user is opening a printer:
1584          * NT doesn't let us connect to a printer if the connecting user
1585          * doesn't have print permission.
1586          *
1587          * Third case: user is opening a Port Monitor
1588          * access checks same as opening a handle to the print server.
1589          */
1590
1591         switch (Printer->printer_type )
1592         {
1593         case SPLHND_SERVER:
1594         case SPLHND_PORTMON_TCP:
1595         case SPLHND_PORTMON_LOCAL:
1596                 /* Printserver handles use global struct... */
1597
1598                 snum = -1;
1599
1600                 /* Map standard access rights to object specific access rights */
1601
1602                 se_map_standard(&r->in.access_mask,
1603                                 &printserver_std_mapping);
1604
1605                 /* Deny any object specific bits that don't apply to print
1606                    servers (i.e printer and job specific bits) */
1607
1608                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1609
1610                 if (r->in.access_mask &
1611                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1612                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1613                         close_printer_handle(p, handle);
1614                         ZERO_STRUCTP(r->out.handle);
1615                         return WERR_ACCESS_DENIED;
1616                 }
1617
1618                 /* Allow admin access */
1619
1620                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1621                 {
1622                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1623
1624                         if (!lp_ms_add_printer_wizard()) {
1625                                 close_printer_handle(p, handle);
1626                                 ZERO_STRUCTP(r->out.handle);
1627                                 return WERR_ACCESS_DENIED;
1628                         }
1629
1630                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1631                            and not a printer admin, then fail */
1632
1633                         if ((p->server_info->utok.uid != 0) &&
1634                             !user_has_privileges(p->server_info->ptok,
1635                                                  &se_printop ) &&
1636                             !token_contains_name_in_list(
1637                                     uidtoname(p->server_info->utok.uid),
1638                                     NULL, NULL,
1639                                     p->server_info->ptok,
1640                                     lp_printer_admin(snum))) {
1641                                 close_printer_handle(p, handle);
1642                                 ZERO_STRUCTP(r->out.handle);
1643                                 return WERR_ACCESS_DENIED;
1644                         }
1645
1646                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1647                 }
1648                 else
1649                 {
1650                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1651                 }
1652
1653                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1654                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1655
1656                 /* We fall through to return WERR_OK */
1657                 break;
1658
1659         case SPLHND_PRINTER:
1660                 /* NT doesn't let us connect to a printer if the connecting user
1661                    doesn't have print permission.  */
1662
1663                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1664                         close_printer_handle(p, handle);
1665                         ZERO_STRUCTP(r->out.handle);
1666                         return WERR_BADFID;
1667                 }
1668
1669                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1670
1671                 /* map an empty access mask to the minimum access mask */
1672                 if (r->in.access_mask == 0x0)
1673                         r->in.access_mask = PRINTER_ACCESS_USE;
1674
1675                 /*
1676                  * If we are not serving the printer driver for this printer,
1677                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1678                  * will keep NT clients happy  --jerry
1679                  */
1680
1681                 if (lp_use_client_driver(snum)
1682                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1683                 {
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685                 }
1686
1687                 /* check smb.conf parameters and the the sec_desc */
1688
1689                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1690                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1691                         ZERO_STRUCTP(r->out.handle);
1692                         return WERR_ACCESS_DENIED;
1693                 }
1694
1695                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1696                                    p->server_info->ptok, snum) ||
1697                     !print_access_check(p->server_info, snum,
1698                                         r->in.access_mask)) {
1699                         DEBUG(3, ("access DENIED for printer open\n"));
1700                         close_printer_handle(p, handle);
1701                         ZERO_STRUCTP(r->out.handle);
1702                         return WERR_ACCESS_DENIED;
1703                 }
1704
1705                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1706                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1707                         close_printer_handle(p, handle);
1708                         ZERO_STRUCTP(r->out.handle);
1709                         return WERR_ACCESS_DENIED;
1710                 }
1711
1712                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1713                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1714                 else
1715                         r->in.access_mask = PRINTER_ACCESS_USE;
1716
1717                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1718                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1719
1720                 break;
1721
1722         default:
1723                 /* sanity check to prevent programmer error */
1724                 ZERO_STRUCTP(r->out.handle);
1725                 return WERR_BADFID;
1726         }
1727
1728         Printer->access_granted = r->in.access_mask;
1729
1730         /*
1731          * If the client sent a devmode in the OpenPrinter() call, then
1732          * save it here in case we get a job submission on this handle
1733          */
1734
1735          if ( (Printer->printer_type != SPLHND_SERVER)
1736                 && r->in.devmode_ctr.devmode )
1737          {
1738                 convert_devicemode_new(Printer->sharename,
1739                                        r->in.devmode_ctr.devmode,
1740                                        &Printer->nt_devmode);
1741          }
1742
1743 #if 0   /* JERRY -- I'm doubtful this is really effective */
1744         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1745            optimization in Windows 2000 clients  --jerry */
1746
1747         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1748                 && (RA_WIN2K == get_remote_arch()) )
1749         {
1750                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1751                 sys_usleep( 500000 );
1752         }
1753 #endif
1754
1755         return WERR_OK;
1756 }
1757
1758 /****************************************************************************
1759 ****************************************************************************/
1760
1761 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1762                                               NT_PRINTER_INFO_LEVEL_2 *d)
1763 {
1764         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1765
1766         if (!r || !d) {
1767                 return false;
1768         }
1769
1770         d->attributes           = r->attributes;
1771         d->priority             = r->priority;
1772         d->default_priority     = r->defaultpriority;
1773         d->starttime            = r->starttime;
1774         d->untiltime            = r->untiltime;
1775         d->status               = r->status;
1776         d->cjobs                = r->cjobs;
1777
1778         fstrcpy(d->servername,  r->servername);
1779         fstrcpy(d->printername, r->printername);
1780         fstrcpy(d->sharename,   r->sharename);
1781         fstrcpy(d->portname,    r->portname);
1782         fstrcpy(d->drivername,  r->drivername);
1783         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1784         fstrcpy(d->location,    r->location);
1785         fstrcpy(d->sepfile,     r->sepfile);
1786         fstrcpy(d->printprocessor, r->printprocessor);
1787         fstrcpy(d->datatype,    r->datatype);
1788         fstrcpy(d->parameters,  r->parameters);
1789
1790         return true;
1791 }
1792
1793 /****************************************************************************
1794 ****************************************************************************/
1795
1796 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1797                                      NT_PRINTER_INFO_LEVEL *printer)
1798 {
1799         bool ret;
1800
1801         switch (info_ctr->level) {
1802         case 2:
1803                 /* allocate memory if needed.  Messy because
1804                    convert_printer_info is used to update an existing
1805                    printer or build a new one */
1806
1807                 if (!printer->info_2) {
1808                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1809                         if (!printer->info_2) {
1810                                 DEBUG(0,("convert_printer_info_new: "
1811                                         "talloc() failed!\n"));
1812                                 return false;
1813                         }
1814                 }
1815
1816                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1817                                                         printer->info_2);
1818                 printer->info_2->setuptime = time(NULL);
1819                 return ret;
1820         }
1821
1822         return false;
1823 }
1824
1825 /*******************************************************************
1826 ********************************************************************/
1827
1828 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1829 {
1830         int i;
1831
1832         if (!sarray) {
1833                 *farray = NULL;
1834                 return true;
1835         }
1836
1837         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1838         if (!*farray) {
1839                 return false;
1840         }
1841
1842         for (i=0; sarray[i] != NULL; i++) {
1843                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1844                 if (!*farray) {
1845                         return false;
1846                 }
1847                 fstrcpy((*farray)[i], sarray[i]);
1848         }
1849
1850         fstrcpy((*farray)[i], "");
1851
1852         return true;
1853 }
1854
1855 /*******************************************************************
1856 ********************************************************************/
1857
1858 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1859                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1860 {
1861         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1862
1863         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1864
1865         if (*p == NULL) {
1866                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1867                 if (*p == NULL) {
1868                         return false;
1869                 }
1870                 ZERO_STRUCTP(*p);
1871         }
1872
1873         d = *p;
1874
1875         d->cversion =                   r->version;
1876
1877         fstrcpy(d->name,                r->driver_name);
1878         fstrcpy(d->environment,         r->architecture);
1879         fstrcpy(d->driverpath,          r->driver_path);
1880         fstrcpy(d->datafile,            r->data_file);
1881         fstrcpy(d->configfile,          r->config_file);
1882         fstrcpy(d->helpfile,            r->help_file);
1883         fstrcpy(d->monitorname,         r->monitor_name);
1884         fstrcpy(d->defaultdatatype,     r->default_datatype);
1885
1886         DEBUGADD(8,( "version:         %d\n", d->cversion));
1887         DEBUGADD(8,( "name:            %s\n", d->name));
1888         DEBUGADD(8,( "environment:     %s\n", d->environment));
1889         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1890         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1891         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1892         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1893         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1894         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1895
1896         if (r->dependent_files) {
1897                 if (!string_array_to_fstring_array(r->dependent_files->string,
1898                                                    &d->dependentfiles)) {
1899                         SAFE_FREE(*p);
1900                         return false;
1901                 }
1902         }
1903
1904         return true;
1905 }
1906
1907 /*******************************************************************
1908 ********************************************************************/
1909
1910 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1911                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1912 {
1913         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1914
1915         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1916
1917         if (*p == NULL) {
1918                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1919                 if (*p == NULL) {
1920                         return false;
1921                 }
1922                 ZERO_STRUCTP(*p);
1923         }
1924
1925         d = *p;
1926
1927         d->version =                    r->version;
1928
1929         fstrcpy(d->name,                r->driver_name);
1930         fstrcpy(d->environment,         r->architecture);
1931         fstrcpy(d->driverpath,          r->driver_path);
1932         fstrcpy(d->datafile,            r->data_file);
1933         fstrcpy(d->configfile,          r->config_file);
1934         fstrcpy(d->helpfile,            r->help_file);
1935         fstrcpy(d->monitorname,         r->monitor_name);
1936         fstrcpy(d->defaultdatatype,     r->default_datatype);
1937
1938         DEBUGADD(8,( "version:         %d\n", d->version));
1939         DEBUGADD(8,( "name:            %s\n", d->name));
1940         DEBUGADD(8,( "environment:     %s\n", d->environment));
1941         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1942         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1943         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1944         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1945         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1946         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1947
1948         if (r->dependent_files) {
1949                 if (!string_array_to_fstring_array(r->dependent_files->string,
1950                                                    &d->dependentfiles)) {
1951                         goto error;
1952                 }
1953         }
1954
1955         if (r->previous_names) {
1956                 if (!string_array_to_fstring_array(r->previous_names->string,
1957                                                    &d->previousnames)) {
1958                         goto error;
1959                 }
1960         }
1961
1962         return true;
1963
1964  error:
1965         SAFE_FREE(*p);
1966         return false;
1967 }
1968
1969 /********************************************************************
1970  ********************************************************************/
1971
1972 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1973                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1974                                         uint32_t level)
1975 {
1976         switch (level) {
1977         case 3:
1978                 printer->info_3 = NULL;
1979                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1980                         return false;
1981                 }
1982                 break;
1983         case 6:
1984                 printer->info_6 = NULL;
1985                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1986                         return false;
1987                 }
1988                 break;
1989         default:
1990                 return false;
1991         }
1992
1993         return true;
1994 }
1995
1996 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1997                                 NT_DEVICEMODE **pp_nt_devmode)
1998 {
1999         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
2000
2001         /*
2002          * Ensure nt_devmode is a valid pointer
2003          * as we will be overwriting it.
2004          */
2005
2006         if (nt_devmode == NULL) {
2007                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2008                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2009                         return False;
2010         }
2011
2012         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2013         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2014
2015         nt_devmode->specversion=devmode->specversion;
2016         nt_devmode->driverversion=devmode->driverversion;
2017         nt_devmode->size=devmode->size;
2018         nt_devmode->fields=devmode->fields;
2019         nt_devmode->orientation=devmode->orientation;
2020         nt_devmode->papersize=devmode->papersize;
2021         nt_devmode->paperlength=devmode->paperlength;
2022         nt_devmode->paperwidth=devmode->paperwidth;
2023         nt_devmode->scale=devmode->scale;
2024         nt_devmode->copies=devmode->copies;
2025         nt_devmode->defaultsource=devmode->defaultsource;
2026         nt_devmode->printquality=devmode->printquality;
2027         nt_devmode->color=devmode->color;
2028         nt_devmode->duplex=devmode->duplex;
2029         nt_devmode->yresolution=devmode->yresolution;
2030         nt_devmode->ttoption=devmode->ttoption;
2031         nt_devmode->collate=devmode->collate;
2032
2033         nt_devmode->logpixels=devmode->logpixels;
2034         nt_devmode->bitsperpel=devmode->bitsperpel;
2035         nt_devmode->pelswidth=devmode->pelswidth;
2036         nt_devmode->pelsheight=devmode->pelsheight;
2037         nt_devmode->displayflags=devmode->displayflags;
2038         nt_devmode->displayfrequency=devmode->displayfrequency;
2039         nt_devmode->icmmethod=devmode->icmmethod;
2040         nt_devmode->icmintent=devmode->icmintent;
2041         nt_devmode->mediatype=devmode->mediatype;
2042         nt_devmode->dithertype=devmode->dithertype;
2043         nt_devmode->reserved1=devmode->reserved1;
2044         nt_devmode->reserved2=devmode->reserved2;
2045         nt_devmode->panningwidth=devmode->panningwidth;
2046         nt_devmode->panningheight=devmode->panningheight;
2047
2048         /*
2049          * Only change private and driverextra if the incoming devmode
2050          * has a new one. JRA.
2051          */
2052
2053         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2054                 SAFE_FREE(nt_devmode->nt_dev_private);
2055                 nt_devmode->driverextra=devmode->driverextra;
2056                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2057                         return False;
2058                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2059         }
2060
2061         *pp_nt_devmode = nt_devmode;
2062
2063         return True;
2064 }
2065
2066 /********************************************************************
2067  * _spoolss_enddocprinter_internal.
2068  ********************************************************************/
2069
2070 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2071 {
2072         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2073         int snum;
2074
2075         if (!Printer) {
2076                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2077                 return WERR_BADFID;
2078         }
2079
2080         if (!get_printer_snum(p, handle, &snum, NULL))
2081                 return WERR_BADFID;
2082
2083         Printer->document_started=False;
2084         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2085         /* error codes unhandled so far ... */
2086
2087         return WERR_OK;
2088 }
2089
2090 /****************************************************************
2091  _spoolss_ClosePrinter
2092 ****************************************************************/
2093
2094 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2095                              struct spoolss_ClosePrinter *r)
2096 {
2097         POLICY_HND *handle = r->in.handle;
2098
2099         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2100
2101         if (Printer && Printer->document_started)
2102                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2103
2104         if (!close_printer_handle(p, handle))
2105                 return WERR_BADFID;
2106
2107         /* clear the returned printer handle.  Observed behavior
2108            from Win2k server.  Don't think this really matters.
2109            Previous code just copied the value of the closed
2110            handle.    --jerry */
2111
2112         ZERO_STRUCTP(r->out.handle);
2113
2114         return WERR_OK;
2115 }
2116
2117 /****************************************************************
2118  _spoolss_DeletePrinter
2119 ****************************************************************/
2120
2121 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2122                               struct spoolss_DeletePrinter *r)
2123 {
2124         POLICY_HND *handle = r->in.handle;
2125         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2126         WERROR result;
2127
2128         if (Printer && Printer->document_started)
2129                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2130
2131         result = delete_printer_handle(p, handle);
2132
2133         update_c_setprinter(False);
2134
2135         return result;
2136 }
2137
2138 /*******************************************************************
2139  * static function to lookup the version id corresponding to an
2140  * long architecture string
2141  ******************************************************************/
2142
2143 static int get_version_id (char * arch)
2144 {
2145         int i;
2146         struct table_node archi_table[]= {
2147
2148                 {"Windows 4.0",          "WIN40",       0 },
2149                 {"Windows NT x86",       "W32X86",      2 },
2150                 {"Windows NT R4000",     "W32MIPS",     2 },
2151                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2152                 {"Windows NT PowerPC",   "W32PPC",      2 },
2153                 {"Windows IA64",         "IA64",        3 },
2154                 {"Windows x64",          "x64",         3 },
2155                 {NULL,                   "",            -1 }
2156         };
2157
2158         for (i=0; archi_table[i].long_archi != NULL; i++)
2159         {
2160                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2161                         return (archi_table[i].version);
2162         }
2163
2164         return -1;
2165 }
2166
2167 /****************************************************************
2168  _spoolss_DeletePrinterDriver
2169 ****************************************************************/
2170
2171 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2172                                     struct spoolss_DeletePrinterDriver *r)
2173 {
2174         char *driver;
2175         char *arch;
2176         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2177         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2178         int                             version;
2179         WERROR                          status;
2180         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2181         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2182
2183         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184            and not a printer admin, then fail */
2185
2186         if ( (p->server_info->utok.uid != 0)
2187                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2188                 && !token_contains_name_in_list(
2189                         uidtoname(p->server_info->utok.uid), NULL,
2190                         NULL, p->server_info->ptok,
2191                         lp_printer_admin(-1)) )
2192         {
2193                 return WERR_ACCESS_DENIED;
2194         }
2195
2196         driver = CONST_DISCARD(char *, r->in.driver);
2197         arch   = CONST_DISCARD(char *, r->in.architecture);
2198
2199         /* check that we have a valid driver name first */
2200
2201         if ((version=get_version_id(arch)) == -1)
2202                 return WERR_INVALID_ENVIRONMENT;
2203
2204         ZERO_STRUCT(info);
2205         ZERO_STRUCT(info_win2k);
2206
2207         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2208         {
2209                 /* try for Win2k driver if "Windows NT x86" */
2210
2211                 if ( version == 2 ) {
2212                         version = 3;
2213                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2214                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2215                                 goto done;
2216                         }
2217                 }
2218                 /* otherwise it was a failure */
2219                 else {
2220                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2221                         goto done;
2222                 }
2223
2224         }
2225
2226         if (printer_driver_in_use(info.info_3)) {
2227                 status = WERR_PRINTER_DRIVER_IN_USE;
2228                 goto done;
2229         }
2230
2231         if ( version == 2 )
2232         {
2233                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2234                 {
2235                         /* if we get to here, we now have 2 driver info structures to remove */
2236                         /* remove the Win2k driver first*/
2237
2238                         status_win2k = delete_printer_driver(
2239                                 p, info_win2k.info_3, 3, False );
2240                         free_a_printer_driver( info_win2k, 3 );
2241
2242                         /* this should not have failed---if it did, report to client */
2243                         if ( !W_ERROR_IS_OK(status_win2k) )
2244                         {
2245                                 status = status_win2k;
2246                                 goto done;
2247                         }
2248                 }
2249         }
2250
2251         status = delete_printer_driver(p, info.info_3, version, False);
2252
2253         /* if at least one of the deletes succeeded return OK */
2254
2255         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2256                 status = WERR_OK;
2257
2258 done:
2259         free_a_printer_driver( info, 3 );
2260
2261         return status;
2262 }
2263
2264 /****************************************************************
2265  _spoolss_DeletePrinterDriverEx
2266 ****************************************************************/
2267
2268 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2269                                       struct spoolss_DeletePrinterDriverEx *r)
2270 {
2271         char *driver;
2272         char *arch;
2273         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2274         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2275         int                             version;
2276         uint32_t                        flags = r->in.delete_flags;
2277         bool                            delete_files;
2278         WERROR                          status;
2279         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2280         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2281
2282         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2283            and not a printer admin, then fail */
2284
2285         if ( (p->server_info->utok.uid != 0)
2286                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2287                 && !token_contains_name_in_list(
2288                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2289                         p->server_info->ptok, lp_printer_admin(-1)) )
2290         {
2291                 return WERR_ACCESS_DENIED;
2292         }
2293
2294         driver = CONST_DISCARD(char *, r->in.driver);
2295         arch   = CONST_DISCARD(char *, r->in.architecture);
2296
2297         /* check that we have a valid driver name first */
2298         if ((version=get_version_id(arch)) == -1) {
2299                 /* this is what NT returns */
2300                 return WERR_INVALID_ENVIRONMENT;
2301         }
2302
2303         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2304                 version = r->in.version;
2305
2306         ZERO_STRUCT(info);
2307         ZERO_STRUCT(info_win2k);
2308
2309         status = get_a_printer_driver(&info, 3, driver, arch, version);
2310
2311         if ( !W_ERROR_IS_OK(status) )
2312         {
2313                 /*
2314                  * if the client asked for a specific version,
2315                  * or this is something other than Windows NT x86,
2316                  * then we've failed
2317                  */
2318
2319                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2320                         goto done;
2321
2322                 /* try for Win2k driver if "Windows NT x86" */
2323
2324                 version = 3;
2325                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2326                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2327                         goto done;
2328                 }
2329         }
2330
2331         if ( printer_driver_in_use(info.info_3) ) {
2332                 status = WERR_PRINTER_DRIVER_IN_USE;
2333                 goto done;
2334         }
2335
2336         /*
2337          * we have a couple of cases to consider.
2338          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2339          *     then the delete should fail if **any** files overlap with
2340          *     other drivers
2341          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2342          *     non-overlapping files
2343          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2344          *     is set, the do not delete any files
2345          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2346          */
2347
2348         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2349
2350         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2351
2352         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2353                 /* no idea of the correct error here */
2354                 status = WERR_ACCESS_DENIED;
2355                 goto done;
2356         }
2357
2358
2359         /* also check for W32X86/3 if necessary; maybe we already have? */
2360
2361         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2362                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2363                 {
2364
2365                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2366                                 /* no idea of the correct error here */
2367                                 free_a_printer_driver( info_win2k, 3 );
2368                                 status = WERR_ACCESS_DENIED;
2369                                 goto done;
2370                         }
2371
2372                         /* if we get to here, we now have 2 driver info structures to remove */
2373                         /* remove the Win2k driver first*/
2374
2375                         status_win2k = delete_printer_driver(
2376                                 p, info_win2k.info_3, 3, delete_files);
2377                         free_a_printer_driver( info_win2k, 3 );
2378
2379                         /* this should not have failed---if it did, report to client */
2380
2381                         if ( !W_ERROR_IS_OK(status_win2k) )
2382                                 goto done;
2383                 }
2384         }
2385
2386         status = delete_printer_driver(p, info.info_3, version, delete_files);
2387
2388         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2389                 status = WERR_OK;
2390 done:
2391         free_a_printer_driver( info, 3 );
2392
2393         return status;
2394 }
2395
2396
2397 /****************************************************************************
2398  Internal routine for retreiving printerdata
2399  ***************************************************************************/
2400
2401 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2402                                   const char *key, const char *value, uint32 *type, uint8 **data,
2403                                   uint32 *needed, uint32 in_size  )
2404 {
2405         REGISTRY_VALUE          *val;
2406         uint32                  size;
2407         int                     data_len;
2408
2409         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2410                 return WERR_BADFILE;
2411
2412         *type = regval_type( val );
2413
2414         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2415
2416         size = regval_size( val );
2417
2418         /* copy the min(in_size, len) */
2419
2420         if ( in_size ) {
2421                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2422
2423                 /* special case for 0 length values */
2424                 if ( data_len ) {
2425                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2426                                 return WERR_NOMEM;
2427                 }
2428                 else {
2429                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2430                                 return WERR_NOMEM;
2431                 }
2432         }
2433         else
2434                 *data = NULL;
2435
2436         *needed = size;
2437
2438         DEBUG(5,("get_printer_dataex: copy done\n"));
2439
2440         return WERR_OK;
2441 }
2442
2443 /****************************************************************************
2444  Internal routine for removing printerdata
2445  ***************************************************************************/
2446
2447 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2448 {
2449         return delete_printer_data( printer->info_2, key, value );
2450 }
2451
2452 /****************************************************************************
2453  Internal routine for storing printerdata
2454  ***************************************************************************/
2455
2456 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2457                                   uint32 type, uint8 *data, int real_len  )
2458 {
2459         /* the registry objects enforce uniqueness based on value name */
2460
2461         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2462 }
2463
2464 /********************************************************************
2465  GetPrinterData on a printer server Handle.
2466 ********************************************************************/
2467
2468 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2469                                             const char *value,
2470                                             enum winreg_Type *type,
2471                                             union spoolss_PrinterData *data)
2472 {
2473         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2474
2475         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2476                 *type = REG_DWORD;
2477                 data->value = 0x00;
2478                 return WERR_OK;
2479         }
2480
2481         if (!StrCaseCmp(value, "BeepEnabled")) {
2482                 *type = REG_DWORD;
2483                 data->value = 0x00;
2484                 return WERR_OK;
2485         }
2486
2487         if (!StrCaseCmp(value, "EventLog")) {
2488                 *type = REG_DWORD;
2489                 /* formally was 0x1b */
2490                 data->value = 0x00;
2491                 return WERR_OK;
2492         }
2493
2494         if (!StrCaseCmp(value, "NetPopup")) {
2495                 *type = REG_DWORD;
2496                 data->value = 0x00;
2497                 return WERR_OK;
2498         }
2499
2500         if (!StrCaseCmp(value, "MajorVersion")) {
2501                 *type = REG_DWORD;
2502
2503                 /* Windows NT 4.0 seems to not allow uploading of drivers
2504                    to a server that reports 0x3 as the MajorVersion.
2505                    need to investigate more how Win2k gets around this .
2506                    -- jerry */
2507
2508                 if (RA_WINNT == get_remote_arch()) {
2509                         data->value = 0x02;
2510                 } else {
2511                         data->value = 0x03;
2512                 }
2513
2514                 return WERR_OK;
2515         }
2516
2517         if (!StrCaseCmp(value, "MinorVersion")) {
2518                 *type = REG_DWORD;
2519                 data->value = 0x00;
2520                 return WERR_OK;
2521         }
2522
2523         /* REG_BINARY
2524          *  uint32 size          = 0x114
2525          *  uint32 major         = 5
2526          *  uint32 minor         = [0|1]
2527          *  uint32 build         = [2195|2600]
2528          *  extra unicode string = e.g. "Service Pack 3"
2529          */
2530         if (!StrCaseCmp(value, "OSVersion")) {
2531                 DATA_BLOB blob;
2532                 enum ndr_err_code ndr_err;
2533                 struct spoolss_OSVersion os;
2534
2535                 os.major                = 5;    /* Windows 2000 == 5.0 */
2536                 os.minor                = 0;
2537                 os.build                = 2195; /* build */
2538                 os.extra_string         = "";   /* leave extra string empty */
2539
2540                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2541                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2542                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2543                         return WERR_GENERAL_FAILURE;
2544                 }
2545
2546                 *type = REG_BINARY;
2547                 data->binary = blob;
2548
2549                 return WERR_OK;
2550         }
2551
2552
2553         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2554                 *type = REG_SZ;
2555
2556                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2557                 W_ERROR_HAVE_NO_MEMORY(data->string);
2558
2559                 return WERR_OK;
2560         }
2561
2562         if (!StrCaseCmp(value, "Architecture")) {
2563                 *type = REG_SZ;
2564
2565                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2566                 W_ERROR_HAVE_NO_MEMORY(data->string);
2567
2568                 return WERR_OK;
2569         }
2570
2571         if (!StrCaseCmp(value, "DsPresent")) {
2572                 *type = REG_DWORD;
2573
2574                 /* only show the publish check box if we are a
2575                    member of a AD domain */
2576
2577                 if (lp_security() == SEC_ADS) {
2578                         data->value = 0x01;
2579                 } else {
2580                         data->value = 0x00;
2581                 }
2582                 return WERR_OK;
2583         }
2584
2585         if (!StrCaseCmp(value, "DNSMachineName")) {
2586                 const char *hostname = get_mydnsfullname();
2587
2588                 if (!hostname) {
2589                         return WERR_BADFILE;
2590                 }
2591
2592                 *type = REG_SZ;
2593                 data->string = talloc_strdup(mem_ctx, hostname);
2594                 W_ERROR_HAVE_NO_MEMORY(data->string);
2595
2596                 return WERR_OK;
2597         }
2598
2599         return WERR_BADFILE;
2600 }
2601
2602 /****************************************************************
2603  _spoolss_GetPrinterData
2604 ****************************************************************/
2605
2606 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2607                                struct spoolss_GetPrinterData *r)
2608 {
2609         WERROR result;
2610         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2611         NT_PRINTER_INFO_LEVEL *printer = NULL;
2612         int snum = 0;
2613
2614         /*
2615          * Reminder: when it's a string, the length is in BYTES
2616          * even if UNICODE is negociated.
2617          *
2618          * JFM, 4/19/1999
2619          */
2620
2621         /* in case of problem, return some default values */
2622
2623         *r->out.needed  = 0;
2624         *r->out.type    = 0;
2625
2626         DEBUG(4,("_spoolss_GetPrinterData\n"));
2627
2628         if (!Printer) {
2629                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2630                         OUR_HANDLE(r->in.handle)));
2631                 result = WERR_BADFID;
2632                 goto done;
2633         }
2634
2635         if (Printer->printer_type == SPLHND_SERVER) {
2636                 result = getprinterdata_printer_server(p->mem_ctx,
2637                                                        r->in.value_name,
2638                                                        r->out.type,
2639                                                        r->out.data);
2640         } else {
2641                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2642                         result = WERR_BADFID;
2643                         goto done;
2644                 }
2645
2646                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2647                 if (!W_ERROR_IS_OK(result)) {
2648                         goto done;
2649                 }
2650
2651                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2652
2653                 if (strequal(r->in.value_name, "ChangeId")) {
2654                         *r->out.type = REG_DWORD;
2655                         r->out.data->value = printer->info_2->changeid;
2656                         result = WERR_OK;
2657                 } else {
2658                         REGISTRY_VALUE *v;
2659                         DATA_BLOB blob;
2660
2661                         v = get_printer_data(printer->info_2,
2662                                              SPOOL_PRINTERDATA_KEY,
2663                                              r->in.value_name);
2664                         if (!v) {
2665                                 result = WERR_BADFILE;
2666                                 goto done;
2667                         }
2668
2669                         *r->out.type = v->type;
2670
2671                         blob = data_blob_const(v->data_p, v->size);
2672
2673                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2674                                                           r->out.data,
2675                                                           *r->out.type);
2676                 }
2677         }
2678
2679  done:
2680         /* cleanup & exit */
2681
2682         if (printer) {
2683                 free_a_printer(&printer, 2);
2684         }
2685
2686         if (!W_ERROR_IS_OK(result)) {
2687                 return result;
2688         }
2689
2690         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2691         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2692         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2693
2694         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2695 }
2696
2697 /*********************************************************
2698  Connect to the client machine.
2699 **********************************************************/
2700
2701 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2702                         struct sockaddr_storage *client_ss, const char *remote_machine)
2703 {
2704         NTSTATUS ret;
2705         struct cli_state *the_cli;
2706         struct sockaddr_storage rm_addr;
2707
2708         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2709                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2710                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2711                         return False;
2712                 }
2713
2714                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2715                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2716                         return False;
2717                 }
2718         } else {
2719                 char addr[INET6_ADDRSTRLEN];
2720                 rm_addr = *client_ss;
2721                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2722                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2723                         addr));
2724         }
2725
2726         /* setup the connection */
2727
2728         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2729                 &rm_addr, 0, "IPC$", "IPC",
2730                 "", /* username */
2731                 "", /* domain */
2732                 "", /* password */
2733                 0, lp_client_signing(), NULL );
2734
2735         if ( !NT_STATUS_IS_OK( ret ) ) {
2736                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2737                         remote_machine ));
2738                 return False;
2739         }
2740
2741         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2742                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2743                 cli_shutdown(the_cli);
2744                 return False;
2745         }
2746
2747         /*
2748          * Ok - we have an anonymous connection to the IPC$ share.
2749          * Now start the NT Domain stuff :-).
2750          */
2751
2752         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2753         if (!NT_STATUS_IS_OK(ret)) {
2754                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2755                         remote_machine, nt_errstr(ret)));
2756                 cli_shutdown(the_cli);
2757                 return False;
2758         }
2759
2760         return True;
2761 }
2762
2763 /***************************************************************************
2764  Connect to the client.
2765 ****************************************************************************/
2766
2767 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2768                                         uint32 localprinter, uint32 type,
2769                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2770 {
2771         WERROR result;
2772         NTSTATUS status;
2773
2774         /*
2775          * If it's the first connection, contact the client
2776          * and connect to the IPC$ share anonymously
2777          */
2778         if (smb_connections==0) {
2779                 fstring unix_printer;
2780
2781                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2782
2783                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2784                         return False;
2785
2786                 messaging_register(smbd_messaging_context(), NULL,
2787                                    MSG_PRINTER_NOTIFY2,
2788                                    receive_notify2_message_list);
2789                 /* Tell the connections db we're now interested in printer
2790                  * notify messages. */
2791                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2792         }
2793
2794         /*
2795          * Tell the specific printing tdb we want messages for this printer
2796          * by registering our PID.
2797          */
2798
2799         if (!print_notify_register_pid(snum))
2800                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2801
2802         smb_connections++;
2803
2804         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2805                                                  printer,
2806                                                  localprinter,
2807                                                  type,
2808                                                  0,
2809                                                  NULL,
2810                                                  handle,
2811                                                  &result);
2812         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2813                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2814                         win_errstr(result)));
2815
2816         return (W_ERROR_IS_OK(result));
2817 }
2818
2819 /****************************************************************
2820  ****************************************************************/
2821
2822 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2823                                                              const struct spoolss_NotifyOption *r)
2824 {
2825         struct spoolss_NotifyOption *option;
2826         uint32_t i,k;
2827
2828         if (!r) {
2829                 return NULL;
2830         }
2831
2832         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2833         if (!option) {
2834                 return NULL;
2835         }
2836
2837         *option = *r;
2838
2839         if (!option->count) {
2840                 return option;
2841         }
2842
2843         option->types = talloc_zero_array(option,
2844                 struct spoolss_NotifyOptionType, option->count);
2845         if (!option->types) {
2846                 talloc_free(option);
2847                 return NULL;
2848         }
2849
2850         for (i=0; i < option->count; i++) {
2851                 option->types[i] = r->types[i];
2852
2853                 if (option->types[i].count) {
2854                         option->types[i].fields = talloc_zero_array(option,
2855                                 enum spoolss_Field, option->types[i].count);
2856                         if (!option->types[i].fields) {
2857                                 talloc_free(option);
2858                                 return NULL;
2859                         }
2860                         for (k=0; k<option->types[i].count; k++) {
2861                                 option->types[i].fields[k] =
2862                                         r->types[i].fields[k];
2863                         }
2864                 }
2865         }
2866
2867         return option;
2868 }
2869
2870 /****************************************************************
2871  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2872  *
2873  * before replying OK: status=0 a rpc call is made to the workstation
2874  * asking ReplyOpenPrinter
2875  *
2876  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2877  * called from api_spoolss_rffpcnex
2878 ****************************************************************/
2879
2880 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2881                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2882 {
2883         POLICY_HND *handle = r->in.handle;
2884         int snum = -1;
2885         struct spoolss_NotifyOption *option = r->in.notify_options;
2886         struct sockaddr_storage client_ss;
2887
2888         /* store the notify value in the printer struct */
2889
2890         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2891
2892         if (!Printer) {
2893                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2894                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2895                 return WERR_BADFID;
2896         }
2897
2898         Printer->notify.flags           = r->in.flags;
2899         Printer->notify.options         = r->in.options;
2900         Printer->notify.printerlocal    = r->in.printer_local;
2901
2902         TALLOC_FREE(Printer->notify.option);
2903         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2904
2905         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2906
2907         /* Connect to the client machine and send a ReplyOpenPrinter */
2908
2909         if ( Printer->printer_type == SPLHND_SERVER)
2910                 snum = -1;
2911         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2912                         !get_printer_snum(p, handle, &snum, NULL) )
2913                 return WERR_BADFID;
2914
2915         if (!interpret_string_addr(&client_ss, p->client_address,
2916                                    AI_NUMERICHOST)) {
2917                 return WERR_SERVER_UNAVAILABLE;
2918         }
2919
2920         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2921                                         Printer->notify.printerlocal, 1,
2922                                         &Printer->notify.client_hnd, &client_ss))
2923                 return WERR_SERVER_UNAVAILABLE;
2924
2925         Printer->notify.client_connected=True;
2926
2927         return WERR_OK;
2928 }
2929
2930 /*******************************************************************
2931  * fill a notify_info_data with the servername
2932  ********************************************************************/
2933
2934 void spoolss_notify_server_name(int snum,
2935                                        struct spoolss_Notify *data,
2936                                        print_queue_struct *queue,
2937                                        NT_PRINTER_INFO_LEVEL *printer,
2938                                        TALLOC_CTX *mem_ctx)
2939 {
2940         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2941 }
2942
2943 /*******************************************************************
2944  * fill a notify_info_data with the printername (not including the servername).
2945  ********************************************************************/
2946
2947 void spoolss_notify_printer_name(int snum,
2948                                         struct spoolss_Notify *data,
2949                                         print_queue_struct *queue,
2950                                         NT_PRINTER_INFO_LEVEL *printer,
2951                                         TALLOC_CTX *mem_ctx)
2952 {
2953         /* the notify name should not contain the \\server\ part */
2954         char *p = strrchr(printer->info_2->printername, '\\');
2955
2956         if (!p) {
2957                 p = printer->info_2->printername;
2958         } else {
2959                 p++;
2960         }
2961
2962         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2963 }
2964
2965 /*******************************************************************
2966  * fill a notify_info_data with the servicename
2967  ********************************************************************/
2968
2969 void spoolss_notify_share_name(int snum,
2970                                       struct spoolss_Notify *data,
2971                                       print_queue_struct *queue,
2972                                       NT_PRINTER_INFO_LEVEL *printer,
2973                                       TALLOC_CTX *mem_ctx)
2974 {
2975         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2976 }
2977
2978 /*******************************************************************
2979  * fill a notify_info_data with the port name
2980  ********************************************************************/
2981
2982 void spoolss_notify_port_name(int snum,
2983                                      struct spoolss_Notify *data,
2984                                      print_queue_struct *queue,
2985                                      NT_PRINTER_INFO_LEVEL *printer,
2986                                      TALLOC_CTX *mem_ctx)
2987 {
2988         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the printername
2993  * but it doesn't exist, have to see what to do
2994  ********************************************************************/
2995
2996 void spoolss_notify_driver_name(int snum,
2997                                        struct spoolss_Notify *data,
2998                                        print_queue_struct *queue,
2999                                        NT_PRINTER_INFO_LEVEL *printer,
3000                                        TALLOC_CTX *mem_ctx)
3001 {
3002         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the comment
3007  ********************************************************************/
3008
3009 void spoolss_notify_comment(int snum,
3010                                    struct spoolss_Notify *data,
3011                                    print_queue_struct *queue,
3012                                    NT_PRINTER_INFO_LEVEL *printer,
3013                                    TALLOC_CTX *mem_ctx)
3014 {
3015         char *p;
3016
3017         if (*printer->info_2->comment == '\0') {
3018                 p = lp_comment(snum);
3019         } else {
3020                 p = printer->info_2->comment;
3021         }
3022
3023         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3024 }
3025
3026 /*******************************************************************
3027  * fill a notify_info_data with the comment
3028  * location = "Room 1, floor 2, building 3"
3029  ********************************************************************/
3030
3031 void spoolss_notify_location(int snum,
3032                                     struct spoolss_Notify *data,
3033                                     print_queue_struct *queue,
3034                                     NT_PRINTER_INFO_LEVEL *printer,
3035                                     TALLOC_CTX *mem_ctx)
3036 {
3037         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3038 }
3039
3040 /*******************************************************************
3041  * fill a notify_info_data with the device mode
3042  * jfm:xxxx don't to it for know but that's a real problem !!!
3043  ********************************************************************/
3044
3045 static void spoolss_notify_devmode(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         /* for a dummy implementation we have to zero the fields */
3052         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3053 }
3054
3055 /*******************************************************************
3056  * fill a notify_info_data with the separator file name
3057  ********************************************************************/
3058
3059 void spoolss_notify_sepfile(int snum,
3060                                    struct spoolss_Notify *data,
3061                                    print_queue_struct *queue,
3062                                    NT_PRINTER_INFO_LEVEL *printer,
3063                                    TALLOC_CTX *mem_ctx)
3064 {
3065         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3066 }
3067
3068 /*******************************************************************
3069  * fill a notify_info_data with the print processor
3070  * jfm:xxxx return always winprint to indicate we don't do anything to it
3071  ********************************************************************/
3072
3073 void spoolss_notify_print_processor(int snum,
3074                                            struct spoolss_Notify *data,
3075                                            print_queue_struct *queue,
3076                                            NT_PRINTER_INFO_LEVEL *printer,
3077                                            TALLOC_CTX *mem_ctx)
3078 {
3079         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3080 }
3081
3082 /*******************************************************************
3083  * fill a notify_info_data with the print processor options
3084  * jfm:xxxx send an empty string
3085  ********************************************************************/
3086
3087 void spoolss_notify_parameters(int snum,
3088                                       struct spoolss_Notify *data,
3089                                       print_queue_struct *queue,
3090                                       NT_PRINTER_INFO_LEVEL *printer,
3091                                       TALLOC_CTX *mem_ctx)
3092 {
3093         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3094 }
3095
3096 /*******************************************************************
3097  * fill a notify_info_data with the data type
3098  * jfm:xxxx always send RAW as data type
3099  ********************************************************************/
3100
3101 void spoolss_notify_datatype(int snum,
3102                                     struct spoolss_Notify *data,
3103                                     print_queue_struct *queue,
3104                                     NT_PRINTER_INFO_LEVEL *printer,
3105                                     TALLOC_CTX *mem_ctx)
3106 {
3107         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3108 }
3109
3110 /*******************************************************************
3111  * fill a notify_info_data with the security descriptor
3112  * jfm:xxxx send an null pointer to say no security desc
3113  * have to implement security before !
3114  ********************************************************************/
3115
3116 static void spoolss_notify_security_desc(int snum,
3117                                          struct spoolss_Notify *data,
3118                                          print_queue_struct *queue,
3119                                          NT_PRINTER_INFO_LEVEL *printer,
3120                                          TALLOC_CTX *mem_ctx)
3121 {
3122         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3123                                           printer->info_2->secdesc_buf->sd_size,
3124                                           printer->info_2->secdesc_buf->sd);
3125 }
3126
3127 /*******************************************************************
3128  * fill a notify_info_data with the attributes
3129  * jfm:xxxx a samba printer is always shared
3130  ********************************************************************/
3131
3132 void spoolss_notify_attributes(int snum,
3133                                       struct spoolss_Notify *data,
3134                                       print_queue_struct *queue,
3135                                       NT_PRINTER_INFO_LEVEL *printer,
3136                                       TALLOC_CTX *mem_ctx)
3137 {
3138         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3139 }
3140
3141 /*******************************************************************
3142  * fill a notify_info_data with the priority
3143  ********************************************************************/
3144
3145 static void spoolss_notify_priority(int snum,
3146                                     struct spoolss_Notify *data,
3147                                     print_queue_struct *queue,
3148                                     NT_PRINTER_INFO_LEVEL *printer,
3149                                     TALLOC_CTX *mem_ctx)
3150 {
3151         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3152 }
3153
3154 /*******************************************************************
3155  * fill a notify_info_data with the default priority
3156  ********************************************************************/
3157
3158 static void spoolss_notify_default_priority(int snum,
3159                                             struct spoolss_Notify *data,
3160                                             print_queue_struct *queue,
3161                                             NT_PRINTER_INFO_LEVEL *printer,
3162                                             TALLOC_CTX *mem_ctx)
3163 {
3164         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3165 }
3166
3167 /*******************************************************************
3168  * fill a notify_info_data with the start time
3169  ********************************************************************/
3170
3171 static void spoolss_notify_start_time(int snum,
3172                                       struct spoolss_Notify *data,
3173                                       print_queue_struct *queue,
3174                                       NT_PRINTER_INFO_LEVEL *printer,
3175                                       TALLOC_CTX *mem_ctx)
3176 {
3177         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3178 }
3179
3180 /*******************************************************************
3181  * fill a notify_info_data with the until time
3182  ********************************************************************/
3183
3184 static void spoolss_notify_until_time(int snum,
3185                                       struct spoolss_Notify *data,
3186                                       print_queue_struct *queue,
3187                                       NT_PRINTER_INFO_LEVEL *printer,
3188                                       TALLOC_CTX *mem_ctx)
3189 {
3190         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3191 }
3192
3193 /*******************************************************************
3194  * fill a notify_info_data with the status
3195  ********************************************************************/
3196
3197 static void spoolss_notify_status(int snum,
3198                                   struct spoolss_Notify *data,
3199                                   print_queue_struct *queue,
3200                                   NT_PRINTER_INFO_LEVEL *printer,
3201                                   TALLOC_CTX *mem_ctx)
3202 {
3203         print_status_struct status;
3204
3205         print_queue_length(snum, &status);
3206         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3207 }
3208
3209 /*******************************************************************
3210  * fill a notify_info_data with the number of jobs queued
3211  ********************************************************************/
3212
3213 void spoolss_notify_cjobs(int snum,
3214                                  struct spoolss_Notify *data,
3215                                  print_queue_struct *queue,
3216                                  NT_PRINTER_INFO_LEVEL *printer,
3217                                  TALLOC_CTX *mem_ctx)
3218 {
3219         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3220 }
3221
3222 /*******************************************************************
3223  * fill a notify_info_data with the average ppm
3224  ********************************************************************/
3225
3226 static void spoolss_notify_average_ppm(int snum,
3227                                        struct spoolss_Notify *data,
3228                                        print_queue_struct *queue,
3229                                        NT_PRINTER_INFO_LEVEL *printer,
3230                                        TALLOC_CTX *mem_ctx)
3231 {
3232         /* always respond 8 pages per minutes */
3233         /* a little hard ! */
3234         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3235 }
3236
3237 /*******************************************************************
3238  * fill a notify_info_data with username
3239  ********************************************************************/
3240
3241 static void spoolss_notify_username(int snum,
3242                                     struct spoolss_Notify *data,
3243                                     print_queue_struct *queue,
3244                                     NT_PRINTER_INFO_LEVEL *printer,
3245                                     TALLOC_CTX *mem_ctx)
3246 {
3247         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3248 }
3249
3250 /*******************************************************************
3251  * fill a notify_info_data with job status
3252  ********************************************************************/
3253
3254 static void spoolss_notify_job_status(int snum,
3255                                       struct spoolss_Notify *data,
3256                                       print_queue_struct *queue,
3257                                       NT_PRINTER_INFO_LEVEL *printer,
3258                                       TALLOC_CTX *mem_ctx)
3259 {
3260         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3261 }
3262
3263 /*******************************************************************
3264  * fill a notify_info_data with job name
3265  ********************************************************************/
3266
3267 static void spoolss_notify_job_name(int snum,
3268                                     struct spoolss_Notify *data,
3269                                     print_queue_struct *queue,
3270                                     NT_PRINTER_INFO_LEVEL *printer,
3271                                     TALLOC_CTX *mem_ctx)
3272 {
3273         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3274 }
3275
3276 /*******************************************************************
3277  * fill a notify_info_data with job status
3278  ********************************************************************/
3279
3280 static void spoolss_notify_job_status_string(int snum,
3281                                              struct spoolss_Notify *data,
3282                                              print_queue_struct *queue,
3283                                              NT_PRINTER_INFO_LEVEL *printer,
3284                                              TALLOC_CTX *mem_ctx)
3285 {
3286         /*
3287          * Now we're returning job status codes we just return a "" here. JRA.
3288          */
3289
3290         const char *p = "";
3291
3292 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3293         p = "unknown";
3294
3295         switch (queue->status) {
3296         case LPQ_QUEUED:
3297                 p = "Queued";
3298                 break;
3299         case LPQ_PAUSED:
3300                 p = "";    /* NT provides the paused string */
3301                 break;
3302         case LPQ_SPOOLING:
3303                 p = "Spooling";
3304                 break;
3305         case LPQ_PRINTING:
3306                 p = "Printing";
3307                 break;
3308         }
3309 #endif /* NO LONGER NEEDED. */
3310
3311         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3312 }
3313
3314 /*******************************************************************
3315  * fill a notify_info_data with job time
3316  ********************************************************************/
3317
3318 static void spoolss_notify_job_time(int snum,
3319                                     struct spoolss_Notify *data,
3320                                     print_queue_struct *queue,
3321                                     NT_PRINTER_INFO_LEVEL *printer,
3322                                     TALLOC_CTX *mem_ctx)
3323 {
3324         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3325 }
3326
3327 /*******************************************************************
3328  * fill a notify_info_data with job size
3329  ********************************************************************/
3330
3331 static void spoolss_notify_job_size(int snum,
3332                                     struct spoolss_Notify *data,
3333                                     print_queue_struct *queue,
3334                                     NT_PRINTER_INFO_LEVEL *printer,
3335                                     TALLOC_CTX *mem_ctx)
3336 {
3337         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3338 }
3339
3340 /*******************************************************************
3341  * fill a notify_info_data with page info
3342  ********************************************************************/
3343 static void spoolss_notify_total_pages(int snum,
3344                                 struct spoolss_Notify *data,
3345                                 print_queue_struct *queue,
3346                                 NT_PRINTER_INFO_LEVEL *printer,
3347                                 TALLOC_CTX *mem_ctx)
3348 {
3349         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3350 }
3351
3352 /*******************************************************************
3353  * fill a notify_info_data with pages printed info.
3354  ********************************************************************/
3355 static void spoolss_notify_pages_printed(int snum,
3356                                 struct spoolss_Notify *data,
3357                                 print_queue_struct *queue,
3358                                 NT_PRINTER_INFO_LEVEL *printer,
3359                                 TALLOC_CTX *mem_ctx)
3360 {
3361         /* Add code when back-end tracks this */
3362         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3363 }
3364
3365 /*******************************************************************
3366  Fill a notify_info_data with job position.
3367  ********************************************************************/
3368
3369 static void spoolss_notify_job_position(int snum,
3370                                         struct spoolss_Notify *data,
3371                                         print_queue_struct *queue,
3372                                         NT_PRINTER_INFO_LEVEL *printer,
3373                                         TALLOC_CTX *mem_ctx)
3374 {
3375         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3376 }
3377
3378 /*******************************************************************
3379  Fill a notify_info_data with submitted time.
3380  ********************************************************************/
3381
3382 static void spoolss_notify_submitted_time(int snum,
3383                                           struct spoolss_Notify *data,
3384                                           print_queue_struct *queue,
3385                                           NT_PRINTER_INFO_LEVEL *printer,
3386                                           TALLOC_CTX *mem_ctx)
3387 {
3388         data->data.string.string = NULL;
3389         data->data.string.size = 0;
3390
3391         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3392                                &data->data.string.string,
3393                                &data->data.string.size);
3394
3395 }
3396
3397 struct s_notify_info_data_table
3398 {
3399         enum spoolss_NotifyType type;
3400         enum spoolss_Field field;
3401         const char *name;
3402         enum spoolss_NotifyTable variable_type;
3403         void (*fn) (int snum, struct spoolss_Notify *data,
3404                     print_queue_struct *queue,
3405                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3406 };
3407
3408 /* A table describing the various print notification constants and
3409    whether the notification data is a pointer to a variable sized
3410    buffer, a one value uint32 or a two value uint32. */
3411
3412 static const struct s_notify_info_data_table notify_info_data_table[] =
3413 {
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3440 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3441 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3442 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3443 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3444 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3445 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3446 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3447 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3448 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3449 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3450 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3451 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3452 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3453 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3454 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3455 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3456 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3457 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3458 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3459 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3460 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3461 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3462 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3463 };
3464
3465 /*******************************************************************
3466  Return the variable_type of info_data structure.
3467 ********************************************************************/
3468
3469 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3470                                                   enum spoolss_Field field)
3471 {
3472         int i=0;
3473
3474         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3475                 if ( (notify_info_data_table[i].type == type) &&
3476                      (notify_info_data_table[i].field == field) ) {
3477                         return notify_info_data_table[i].variable_type;
3478                 }
3479         }
3480
3481         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3482
3483         return 0;
3484 }
3485
3486 /****************************************************************************
3487 ****************************************************************************/
3488
3489 static bool search_notify(enum spoolss_NotifyType type,
3490                           enum spoolss_Field field,
3491                           int *value)
3492 {
3493         int i;
3494
3495         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3496                 if (notify_info_data_table[i].type == type &&
3497                     notify_info_data_table[i].field == field &&
3498                     notify_info_data_table[i].fn != NULL) {
3499                         *value = i;
3500                         return True;
3501                 }
3502         }
3503
3504         return False;
3505 }
3506
3507 /****************************************************************************
3508 ****************************************************************************/
3509
3510 void construct_info_data(struct spoolss_Notify *info_data,
3511                          enum spoolss_NotifyType type,
3512                          enum spoolss_Field field,
3513                          int id)
3514 {
3515         info_data->type                 = type;
3516         info_data->field                = field;
3517         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3518         info_data->job_id               = id;
3519 }
3520
3521 /*******************************************************************
3522  *
3523  * fill a notify_info struct with info asked
3524  *
3525  ********************************************************************/
3526
3527 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3528                                           struct spoolss_NotifyInfo *info,
3529                                           int snum,
3530                                           const struct spoolss_NotifyOptionType *option_type,
3531                                           uint32_t id,
3532                                           TALLOC_CTX *mem_ctx)
3533 {
3534         int field_num,j;
3535         enum spoolss_NotifyType type;
3536         enum spoolss_Field field;
3537
3538         struct spoolss_Notify *current_data;
3539         NT_PRINTER_INFO_LEVEL *printer = NULL;
3540         print_queue_struct *queue=NULL;
3541
3542         type = option_type->type;
3543
3544         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3545                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3546                 option_type->count, lp_servicename(snum)));
3547
3548         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3549                 return False;
3550
3551         for(field_num=0; field_num < option_type->count; field_num++) {
3552                 field = option_type->fields[field_num];
3553
3554                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3555
3556                 if (!search_notify(type, field, &j) )
3557                         continue;
3558
3559                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3560                                                       struct spoolss_Notify,
3561                                                       info->count + 1);
3562                 if (info->notifies == NULL) {
3563                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3564                         free_a_printer(&printer, 2);
3565                         return False;
3566                 }
3567
3568                 current_data = &info->notifies[info->count];
3569
3570                 construct_info_data(current_data, type, field, id);
3571
3572                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3573                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3574
3575                 notify_info_data_table[j].fn(snum, current_data, queue,
3576                                              printer, mem_ctx);
3577
3578                 info->count++;
3579         }
3580
3581         free_a_printer(&printer, 2);
3582         return True;
3583 }
3584
3585 /*******************************************************************
3586  *
3587  * fill a notify_info struct with info asked
3588  *
3589  ********************************************************************/
3590
3591 static bool construct_notify_jobs_info(print_queue_struct *queue,
3592                                        struct spoolss_NotifyInfo *info,
3593                                        NT_PRINTER_INFO_LEVEL *printer,
3594                                        int snum,
3595                                        const struct spoolss_NotifyOptionType *option_type,
3596                                        uint32_t id,
3597                                        TALLOC_CTX *mem_ctx)
3598 {
3599         int field_num,j;
3600         enum spoolss_NotifyType type;
3601         enum spoolss_Field field;
3602         struct spoolss_Notify *current_data;
3603
3604         DEBUG(4,("construct_notify_jobs_info\n"));
3605
3606         type = option_type->type;
3607
3608         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3609                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3610                 option_type->count));
3611
3612         for(field_num=0; field_num<option_type->count; field_num++) {
3613                 field = option_type->fields[field_num];
3614
3615                 if (!search_notify(type, field, &j) )
3616                         continue;
3617
3618                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3619                                                       struct spoolss_Notify,
3620                                                       info->count + 1);
3621                 if (info->notifies == NULL) {
3622                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3623                         return False;
3624                 }
3625
3626                 current_data=&(info->notifies[info->count]);
3627
3628                 construct_info_data(current_data, type, field, id);
3629                 notify_info_data_table[j].fn(snum, current_data, queue,
3630                                              printer, mem_ctx);
3631                 info->count++;
3632         }
3633
3634         return True;
3635 }
3636
3637 /*
3638  * JFM: The enumeration is not that simple, it's even non obvious.
3639  *
3640  * let's take an example: I want to monitor the PRINTER SERVER for
3641  * the printer's name and the number of jobs currently queued.
3642  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3643  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3644  *
3645  * I have 3 printers on the back of my server.
3646  *
3647  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3648  * structures.
3649  *   Number     Data                    Id
3650  *      1       printer 1 name          1
3651  *      2       printer 1 cjob          1
3652  *      3       printer 2 name          2
3653  *      4       printer 2 cjob          2
3654  *      5       printer 3 name          3
3655  *      6       printer 3 name          3
3656  *
3657  * that's the print server case, the printer case is even worse.
3658  */
3659
3660 /*******************************************************************
3661  *
3662  * enumerate all printers on the printserver
3663  * fill a notify_info struct with info asked
3664  *
3665  ********************************************************************/
3666
3667 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3668                                       struct spoolss_NotifyInfo *info,
3669                                       TALLOC_CTX *mem_ctx)
3670 {
3671         int snum;
3672         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3673         int n_services=lp_numservices();
3674         int i;
3675         struct spoolss_NotifyOption *option;
3676         struct spoolss_NotifyOptionType option_type;
3677
3678         DEBUG(4,("printserver_notify_info\n"));
3679
3680         if (!Printer)
3681                 return WERR_BADFID;
3682
3683         option = Printer->notify.option;
3684
3685         info->version   = 2;
3686         info->notifies  = NULL;
3687         info->count     = 0;
3688
3689         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3690            sending a ffpcn() request first */
3691
3692         if ( !option )
3693                 return WERR_BADFID;
3694
3695         for (i=0; i<option->count; i++) {
3696                 option_type = option->types[i];
3697
3698                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3699                         continue;
3700
3701                 for (snum=0; snum<n_services; snum++)
3702                 {
3703                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3704                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3705                 }
3706         }
3707
3708 #if 0
3709         /*
3710          * Debugging information, don't delete.
3711          */
3712
3713         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3714         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3715         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716
3717         for (i=0; i<info->count; i++) {
3718                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3719                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3720                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721         }
3722 #endif
3723
3724         return WERR_OK;
3725 }
3726
3727 /*******************************************************************
3728  *
3729  * fill a notify_info struct with info asked
3730  *
3731  ********************************************************************/
3732
3733 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3734                                   TALLOC_CTX *mem_ctx)
3735 {
3736         int snum;
3737         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3738         int i;
3739         uint32 id;
3740         struct spoolss_NotifyOption *option;
3741         struct spoolss_NotifyOptionType option_type;
3742         int count,j;
3743         print_queue_struct *queue=NULL;
3744         print_status_struct status;
3745
3746         DEBUG(4,("printer_notify_info\n"));
3747
3748         if (!Printer)
3749                 return WERR_BADFID;
3750
3751         option = Printer->notify.option;
3752         id = 0x0;
3753
3754         info->version   = 2;
3755         info->notifies  = NULL;
3756         info->count     = 0;
3757
3758         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3759            sending a ffpcn() request first */
3760
3761         if ( !option )
3762                 return WERR_BADFID;
3763
3764         get_printer_snum(p, hnd, &snum, NULL);
3765
3766         for (i=0; i<option->count; i++) {
3767                 option_type = option->types[i];
3768
3769                 switch (option_type.type) {
3770                 case PRINTER_NOTIFY_TYPE:
3771                         if(construct_notify_printer_info(Printer, info, snum,
3772                                                          &option_type, id,
3773                                                          mem_ctx))
3774                                 id--;
3775                         break;
3776
3777                 case JOB_NOTIFY_TYPE: {
3778                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3779
3780                         count = print_queue_status(snum, &queue, &status);
3781
3782                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3783                                 goto done;
3784
3785                         for (j=0; j<count; j++) {
3786                                 construct_notify_jobs_info(&queue[j], info,
3787                                                            printer, snum,
3788                                                            &option_type,
3789                                                            queue[j].job,
3790                                                            mem_ctx);
3791                         }
3792
3793                         free_a_printer(&printer, 2);
3794
3795                 done:
3796                         SAFE_FREE(queue);
3797                         break;
3798                 }
3799                 }
3800         }
3801
3802         /*
3803          * Debugging information, don't delete.
3804          */
3805         /*
3806         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3807         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3808         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3809
3810         for (i=0; i<info->count; i++) {
3811                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3812                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3813                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3814         }
3815         */
3816         return WERR_OK;
3817 }
3818
3819 /****************************************************************
3820  _spoolss_RouterRefreshPrinterChangeNotify
3821 ****************************************************************/
3822
3823 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3824                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3825 {
3826         POLICY_HND *handle = r->in.handle;
3827         struct spoolss_NotifyInfo *info;
3828
3829         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3830         WERROR result = WERR_BADFID;
3831
3832         /* we always have a spoolss_NotifyInfo struct */
3833         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3834         if (!info) {
3835                 result = WERR_NOMEM;
3836                 goto done;
3837         }
3838
3839         *r->out.info = info;
3840
3841         if (!Printer) {
3842                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3843                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3844                 goto done;
3845         }
3846
3847         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3848
3849         /*
3850          *      We are now using the change value, and
3851          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3852          *      I don't have a global notification system, I'm sending back all the
3853          *      informations even when _NOTHING_ has changed.
3854          */
3855
3856         /* We need to keep track of the change value to send back in
3857            RRPCN replies otherwise our updates are ignored. */
3858
3859         Printer->notify.fnpcn = True;
3860
3861         if (Printer->notify.client_connected) {
3862                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3863                         "Saving change value in request [%x]\n",
3864                         r->in.change_low));
3865                 Printer->notify.change = r->in.change_low;
3866         }
3867
3868         /* just ignore the spoolss_NotifyOption */
3869
3870         switch (Printer->printer_type) {
3871                 case SPLHND_SERVER:
3872                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3873                         break;
3874
3875                 case SPLHND_PRINTER:
3876                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3877                         break;
3878         }
3879
3880         Printer->notify.fnpcn = False;
3881
3882 done:
3883         return result;
3884 }
3885
3886 /********************************************************************
3887  * construct_printer_info_0
3888  * fill a printer_info_0 struct
3889  ********************************************************************/
3890
3891 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3892                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3893                                       struct spoolss_PrinterInfo0 *r,
3894                                       int snum)
3895 {
3896         int count;
3897         counter_printer_0 *session_counter;
3898         time_t setuptime;
3899         print_status_struct status;
3900
3901         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3902         W_ERROR_HAVE_NO_MEMORY(r->printername);
3903
3904         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3905         W_ERROR_HAVE_NO_MEMORY(r->servername);
3906
3907         count = print_queue_length(snum, &status);
3908
3909         /* check if we already have a counter for this printer */
3910         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3911                 if (session_counter->snum == snum)
3912                         break;
3913         }
3914
3915         /* it's the first time, add it to the list */
3916         if (session_counter == NULL) {
3917                 session_counter = SMB_MALLOC_P(counter_printer_0);
3918                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3919                 ZERO_STRUCTP(session_counter);
3920                 session_counter->snum           = snum;
3921                 session_counter->counter        = 0;
3922                 DLIST_ADD(counter_list, session_counter);
3923         }
3924
3925         /* increment it */
3926         session_counter->counter++;
3927
3928         r->cjobs                        = count;
3929         r->total_jobs                   = 0;
3930         r->total_bytes                  = 0;
3931
3932         setuptime = (time_t)ntprinter->info_2->setuptime;
3933
3934         init_systemtime(&r->time, gmtime(&setuptime));
3935
3936         /* JFM:
3937          * the global_counter should be stored in a TDB as it's common to all the clients
3938          * and should be zeroed on samba startup
3939          */
3940         r->global_counter               = session_counter->counter;
3941         r->total_pages                  = 0;
3942         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3943         r->version                      = 0x0005;       /* NT 5 */
3944         r->free_build                   = 0x0893;       /* build 2195 */
3945         r->spooling                     = 0;
3946         r->max_spooling                 = 0;
3947         r->session_counter              = session_counter->counter;
3948         r->num_error_out_of_paper       = 0x0;
3949         r->num_error_not_ready          = 0x0;          /* number of print failure */
3950         r->job_error                    = 0x0;
3951         r->number_of_processors         = 0x1;
3952         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3953         r->high_part_total_bytes        = 0x0;
3954         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3955         r->last_error                   = WERR_OK;
3956         r->status                       = nt_printq_status(status.status);
3957         r->enumerate_network_printers   = 0x0;
3958         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3959         r->processor_architecture       = 0x0;
3960         r->processor_level              = 0x6;          /* 6  ???*/
3961         r->ref_ic                       = 0;
3962         r->reserved2                    = 0;
3963         r->reserved3                    = 0;
3964
3965         return WERR_OK;
3966 }
3967
3968 /****************************************************************************
3969  Free a DEVMODE struct.
3970 ****************************************************************************/
3971
3972 static void free_dev_mode(DEVICEMODE *dev)
3973 {
3974         if (dev == NULL)
3975                 return;
3976
3977         SAFE_FREE(dev->dev_private);
3978         SAFE_FREE(dev);
3979 }
3980
3981 /****************************************************************************
3982  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3983  should be valid upon entry
3984 ****************************************************************************/
3985
3986 static WERROR convert_nt_devicemode_new(TALLOC_CTX *mem_ctx,
3987                                         struct spoolss_DeviceMode *r,
3988                                         const NT_DEVICEMODE *ntdevmode)
3989 {
3990         if (!r || !ntdevmode) {
3991                 return WERR_INVALID_PARAM;
3992         }
3993
3994         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3995         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3996
3997         r->specversion          = ntdevmode->specversion;
3998         r->driverversion        = ntdevmode->driverversion;
3999         r->size                 = ntdevmode->size;
4000         r->__driverextra_length = ntdevmode->driverextra;
4001         r->fields               = ntdevmode->fields;
4002
4003         r->orientation          = ntdevmode->orientation;
4004         r->papersize            = ntdevmode->papersize;
4005         r->paperlength          = ntdevmode->paperlength;
4006         r->paperwidth           = ntdevmode->paperwidth;
4007         r->scale                = ntdevmode->scale;
4008         r->copies               = ntdevmode->copies;
4009         r->defaultsource        = ntdevmode->defaultsource;
4010         r->printquality         = ntdevmode->printquality;
4011         r->color                = ntdevmode->color;
4012         r->duplex               = ntdevmode->duplex;
4013         r->yresolution          = ntdevmode->yresolution;
4014         r->ttoption             = ntdevmode->ttoption;
4015         r->collate              = ntdevmode->collate;
4016
4017         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
4018         W_ERROR_HAVE_NO_MEMORY(r->formname);
4019
4020         /* all 0 below are values that have not been set in the old parsing/copy
4021          * function, maybe they should... - gd */
4022
4023         r->logpixels            = 0;
4024         r->bitsperpel           = 0;
4025         r->pelswidth            = 0;
4026         r->pelsheight           = 0;
4027         r->displayflags         = 0;
4028         r->displayfrequency     = 0;
4029         r->icmmethod            = ntdevmode->icmmethod;
4030         r->icmintent            = ntdevmode->icmintent;
4031         r->mediatype            = ntdevmode->mediatype;
4032         r->dithertype           = ntdevmode->dithertype;
4033         r->reserved1            = 0;
4034         r->reserved2            = 0;
4035         r->panningwidth         = 0;
4036         r->panningheight        = 0;
4037
4038         if (ntdevmode->nt_dev_private != NULL) {
4039                 r->driverextra_data = data_blob_talloc(mem_ctx,
4040                         ntdevmode->nt_dev_private,
4041                         ntdevmode->driverextra);
4042                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
4043         }
4044
4045         return WERR_OK;
4046 }
4047
4048
4049 /****************************************************************************
4050  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4051  should be valid upon entry
4052 ****************************************************************************/
4053
4054 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4055 {
4056         if ( !devmode || !ntdevmode )
4057                 return False;
4058
4059         init_unistr(&devmode->devicename, ntdevmode->devicename);
4060
4061         init_unistr(&devmode->formname, ntdevmode->formname);
4062
4063         devmode->specversion      = ntdevmode->specversion;
4064         devmode->driverversion    = ntdevmode->driverversion;
4065         devmode->size             = ntdevmode->size;
4066         devmode->driverextra      = ntdevmode->driverextra;
4067         devmode->fields           = ntdevmode->fields;
4068
4069         devmode->orientation      = ntdevmode->orientation;
4070         devmode->papersize        = ntdevmode->papersize;
4071         devmode->paperlength      = ntdevmode->paperlength;
4072         devmode->paperwidth       = ntdevmode->paperwidth;
4073         devmode->scale            = ntdevmode->scale;
4074         devmode->copies           = ntdevmode->copies;
4075         devmode->defaultsource    = ntdevmode->defaultsource;
4076         devmode->printquality     = ntdevmode->printquality;
4077         devmode->color            = ntdevmode->color;
4078         devmode->duplex           = ntdevmode->duplex;
4079         devmode->yresolution      = ntdevmode->yresolution;
4080         devmode->ttoption         = ntdevmode->ttoption;
4081         devmode->collate          = ntdevmode->collate;
4082         devmode->icmmethod        = ntdevmode->icmmethod;
4083         devmode->icmintent        = ntdevmode->icmintent;
4084         devmode->mediatype        = ntdevmode->mediatype;
4085         devmode->dithertype       = ntdevmode->dithertype;
4086
4087         if (ntdevmode->nt_dev_private != NULL) {
4088                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4089                         return False;
4090         }
4091
4092         return True;
4093 }
4094
4095 /****************************************************************************
4096  Create a spoolss_DeviceMode struct. Returns talloced memory.
4097 ****************************************************************************/
4098
4099 struct spoolss_DeviceMode *construct_dev_mode_new(TALLOC_CTX *mem_ctx,
4100                                                   const char *servicename)
4101 {
4102         WERROR result;
4103         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4104         struct spoolss_DeviceMode *devmode = NULL;
4105
4106         DEBUG(7,("construct_dev_mode_new\n"));
4107
4108         DEBUGADD(8,("getting printer characteristics\n"));
4109
4110         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4111                 return NULL;
4112
4113         if (!printer->info_2->devmode) {
4114                 DEBUG(5, ("BONG! There was no device mode!\n"));
4115                 goto done;
4116         }
4117
4118         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4119         if (!devmode) {
4120                 DEBUG(2,("construct_dev_mode_new: talloc fail.\n"));
4121                 goto done;
4122         }
4123
4124         DEBUGADD(8,("loading DEVICEMODE\n"));
4125
4126         result = convert_nt_devicemode_new(mem_ctx, devmode, printer->info_2->devmode);
4127         if (!W_ERROR_IS_OK(result)) {
4128                 TALLOC_FREE(devmode);
4129         }
4130
4131 done:
4132         free_a_printer(&printer,2);
4133
4134         return devmode;
4135 }
4136
4137 /****************************************************************************
4138  Create a DEVMODE struct. Returns malloced memory.
4139 ****************************************************************************/
4140
4141 DEVICEMODE *construct_dev_mode(const char *servicename)
4142 {
4143         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4144         DEVICEMODE              *devmode = NULL;
4145
4146         DEBUG(7,("construct_dev_mode\n"));
4147
4148         DEBUGADD(8,("getting printer characteristics\n"));
4149
4150         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4151                 return NULL;
4152
4153         if ( !printer->info_2->devmode ) {
4154                 DEBUG(5, ("BONG! There was no device mode!\n"));
4155                 goto done;
4156         }
4157
4158         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4159                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4160                 goto done;
4161         }
4162
4163         ZERO_STRUCTP(devmode);
4164
4165         DEBUGADD(8,("loading DEVICEMODE\n"));
4166
4167         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4168                 free_dev_mode( devmode );
4169                 devmode = NULL;
4170         }
4171
4172 done:
4173         free_a_printer(&printer,2);
4174
4175         return devmode;
4176 }
4177
4178 /********************************************************************
4179  * construct_printer_info3
4180  * fill a spoolss_PrinterInfo3 struct
4181  ********************************************************************/
4182
4183 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4184                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4185                                       struct spoolss_PrinterInfo3 *r,
4186                                       int snum)
4187 {
4188         /* These are the components of the SD we are returning. */
4189
4190         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4191                 /* don't use talloc_steal() here unless you do a deep steal of all
4192                    the SEC_DESC members */
4193
4194                 r->secdesc = dup_sec_desc(mem_ctx,
4195                                           ntprinter->info_2->secdesc_buf->sd);
4196                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4197         }
4198
4199         return WERR_OK;
4200 }
4201
4202 /********************************************************************
4203  * construct_printer_info4
4204  * fill a spoolss_PrinterInfo4 struct
4205  ********************************************************************/
4206
4207 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4208                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4209                                       struct spoolss_PrinterInfo4 *r,
4210                                       int snum)
4211 {
4212         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4213         W_ERROR_HAVE_NO_MEMORY(r->printername);
4214         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4215         W_ERROR_HAVE_NO_MEMORY(r->servername);
4216
4217         r->attributes   = ntprinter->info_2->attributes;
4218
4219         return WERR_OK;
4220 }
4221
4222 /********************************************************************
4223  * construct_printer_info5
4224  * fill a spoolss_PrinterInfo5 struct
4225  ********************************************************************/
4226
4227 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4228                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4229                                       struct spoolss_PrinterInfo5 *r,
4230                                       int snum)
4231 {
4232         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4233         W_ERROR_HAVE_NO_MEMORY(r->printername);
4234         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4235         W_ERROR_HAVE_NO_MEMORY(r->portname);
4236
4237         r->attributes   = ntprinter->info_2->attributes;
4238
4239         /* these two are not used by NT+ according to MSDN */
4240
4241         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4242         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4243
4244         return WERR_OK;
4245 }
4246
4247 /********************************************************************
4248  * construct_printer_info_6
4249  * fill a spoolss_PrinterInfo6 struct
4250  ********************************************************************/
4251
4252 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4253                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4254                                       struct spoolss_PrinterInfo6 *r,
4255                                       int snum)
4256 {
4257         int count;
4258         print_status_struct status;
4259
4260         count = print_queue_length(snum, &status);
4261
4262         r->status = nt_printq_status(status.status);
4263
4264         return WERR_OK;
4265 }
4266
4267 /********************************************************************
4268  * construct_printer_info7
4269  * fill a spoolss_PrinterInfo7 struct
4270  ********************************************************************/
4271
4272 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4273                                       Printer_entry *print_hnd,
4274                                       struct spoolss_PrinterInfo7 *r,
4275                                       int snum)
4276 {
4277         struct GUID guid;
4278
4279         if (is_printer_published(print_hnd, snum, &guid)) {
4280                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4281                 r->action = DSPRINT_PUBLISH;
4282         } else {
4283                 r->guid = talloc_strdup(mem_ctx, "");
4284                 r->action = DSPRINT_UNPUBLISH;
4285         }
4286         W_ERROR_HAVE_NO_MEMORY(r->guid);
4287
4288         return WERR_OK;
4289 }
4290
4291 /********************************************************************
4292  * construct_printer_info1
4293  * fill a spoolss_PrinterInfo1 struct
4294 ********************************************************************/
4295
4296 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4297                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4298                                       uint32_t flags,
4299                                       struct spoolss_PrinterInfo1 *r,
4300                                       int snum)
4301 {
4302         char *chaine = NULL;
4303         r->flags                = flags;
4304
4305         if (*ntprinter->info_2->comment == '\0') {
4306                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4307                 chaine = talloc_asprintf(mem_ctx,
4308                                 "%s,%s,%s", ntprinter->info_2->printername,
4309                                 ntprinter->info_2->drivername, lp_comment(snum));
4310         } else {
4311                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4312                 chaine = talloc_asprintf(mem_ctx,
4313                                 "%s,%s,%s", ntprinter->info_2->printername,
4314                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4315         }
4316         W_ERROR_HAVE_NO_MEMORY(chaine);
4317         W_ERROR_HAVE_NO_MEMORY(r->comment);
4318
4319         r->description          = talloc_strdup(mem_ctx, chaine);
4320         W_ERROR_HAVE_NO_MEMORY(r->description);
4321         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4322         W_ERROR_HAVE_NO_MEMORY(r->name);
4323
4324         return WERR_OK;
4325 }
4326
4327 /********************************************************************
4328  * construct_printer_info2
4329  * fill a spoolss_PrinterInfo2 struct
4330 ********************************************************************/
4331
4332 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4333                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4334                                       struct spoolss_PrinterInfo2 *r,
4335                                       int snum)
4336 {
4337         int count;
4338
4339         print_status_struct status;
4340
4341         count = print_queue_length(snum, &status);
4342
4343         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4344         W_ERROR_HAVE_NO_MEMORY(r->servername);
4345         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4346         W_ERROR_HAVE_NO_MEMORY(r->printername);
4347         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4348         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4349         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4350         W_ERROR_HAVE_NO_MEMORY(r->portname);
4351         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4352         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4353
4354         if (*ntprinter->info_2->comment == '\0') {
4355                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4356         } else {
4357                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4358         }
4359         W_ERROR_HAVE_NO_MEMORY(r->comment);
4360
4361         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4362         W_ERROR_HAVE_NO_MEMORY(r->location);
4363         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4364         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4365         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4366         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4367         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4368         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4369         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4370         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4371
4372         r->attributes           = ntprinter->info_2->attributes;
4373
4374         r->priority             = ntprinter->info_2->priority;
4375         r->defaultpriority      = ntprinter->info_2->default_priority;
4376         r->starttime            = ntprinter->info_2->starttime;
4377         r->untiltime            = ntprinter->info_2->untiltime;
4378         r->status               = nt_printq_status(status.status);
4379         r->cjobs                = count;
4380         r->averageppm           = ntprinter->info_2->averageppm;
4381
4382         r->devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
4383         if (!r->devmode) {
4384                 DEBUG(8,("Returning NULL Devicemode!\n"));
4385         }
4386
4387         r->secdesc              = NULL;
4388
4389         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4390                 /* don't use talloc_steal() here unless you do a deep steal of all
4391                    the SEC_DESC members */
4392
4393                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4394         }
4395
4396         return WERR_OK;
4397 }
4398
4399 /********************************************************************
4400 ********************************************************************/
4401
4402 static bool snum_is_shared_printer(int snum)
4403 {
4404         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4405 }
4406
4407 /********************************************************************
4408  Spoolss_enumprinters.
4409 ********************************************************************/
4410
4411 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4412                                        uint32_t flags,
4413                                        union spoolss_PrinterInfo **info_p,
4414                                        uint32_t *count)
4415 {
4416         int snum;
4417         int n_services = lp_numservices();
4418         union spoolss_PrinterInfo *info = NULL;
4419         WERROR result = WERR_OK;
4420
4421         DEBUG(4,("enum_all_printers_info_1\n"));
4422
4423         *count = 0;
4424
4425         for (snum=0; snum<n_services; snum++) {
4426
4427                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4428                 struct spoolss_PrinterInfo1 info1;
4429
4430                 if (!snum_is_shared_printer(snum)) {
4431                         continue;
4432                 }
4433
4434                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4435
4436                 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4437                 if (!W_ERROR_IS_OK(result)) {
4438                         continue;
4439                 }
4440
4441                 result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4442                 free_a_printer(&ntprinter,2);
4443                 if (!W_ERROR_IS_OK(result)) {
4444                         continue;
4445                 }
4446
4447                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4448                                             union spoolss_PrinterInfo,
4449                                             *count + 1);
4450                 if (!info) {
4451                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4452                         result = WERR_NOMEM;
4453                         goto out;
4454                 }
4455
4456                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4457
4458                 info[*count].info1 = info1;
4459                 (*count)++;
4460         }
4461
4462  out:
4463         if (!W_ERROR_IS_OK(result)) {
4464                 TALLOC_FREE(info);
4465                 *count = 0;
4466                 return result;
4467         }
4468
4469         *info_p = info;
4470
4471         return WERR_OK;
4472 }
4473
4474 /********************************************************************
4475  enum_all_printers_info_1_local.
4476 *********************************************************************/
4477
4478 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4479                                              union spoolss_PrinterInfo **info,
4480                                              uint32_t *count)
4481 {
4482         DEBUG(4,("enum_all_printers_info_1_local\n"));
4483
4484         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4485 }
4486
4487 /********************************************************************
4488  enum_all_printers_info_1_name.
4489 *********************************************************************/
4490
4491 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4492                                             const char *name,
4493                                             union spoolss_PrinterInfo **info,
4494                                             uint32_t *count)
4495 {
4496         const char *s = name;
4497
4498         DEBUG(4,("enum_all_printers_info_1_name\n"));
4499
4500         if ((name[0] == '\\') && (name[1] == '\\')) {
4501                 s = name + 2;
4502         }
4503
4504         if (!is_myname_or_ipaddr(s)) {
4505                 return WERR_INVALID_NAME;
4506         }
4507
4508         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4509 }
4510
4511 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4512 /********************************************************************
4513  enum_all_printers_info_1_remote.
4514 *********************************************************************/
4515
4516 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4517 {
4518         PRINTER_INFO_1 *printer;
4519         fstring printername;
4520         fstring desc;
4521         fstring comment;
4522         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4523         WERROR result = WERR_OK;
4524
4525         /* JFM: currently it's more a place holder than anything else.
4526          * In the spooler world there is a notion of server registration.
4527          * the print servers are registered on the PDC (in the same domain)
4528          *
4529          * We should have a TDB here. The registration is done thru an
4530          * undocumented RPC call.
4531          */
4532
4533         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4534                 return WERR_NOMEM;
4535
4536         *returned=1;
4537
4538         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4539         slprintf(desc, sizeof(desc)-1,"%s", name);
4540         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4541
4542         init_unistr(&printer->description, desc);
4543         init_unistr(&printer->name, printername);
4544         init_unistr(&printer->comment, comment);
4545         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4546
4547         /* check the required size. */
4548         *needed += spoolss_size_printer_info_1(printer);
4549
4550         if (*needed > offered) {
4551                 result = WERR_INSUFFICIENT_BUFFER;
4552                 goto out;
4553         }
4554
4555         if (!rpcbuf_alloc_size(buffer, *needed)) {
4556                 result = WERR_NOMEM;
4557                 goto out;
4558         }
4559
4560         /* fill the buffer with the structures */
4561         smb_io_printer_info_1("", buffer, printer, 0);
4562
4563 out:
4564         /* clear memory */
4565         SAFE_FREE(printer);
4566
4567         if ( !W_ERROR_IS_OK(result) )
4568                 *returned = 0;
4569
4570         return result;
4571 }
4572
4573 #endif
4574
4575 /********************************************************************
4576  enum_all_printers_info_1_network.
4577 *********************************************************************/
4578
4579 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4580                                                const char *name,
4581                                                union spoolss_PrinterInfo **info,
4582                                                uint32_t *count)
4583 {
4584         const char *s = name;
4585
4586         DEBUG(4,("enum_all_printers_info_1_network\n"));
4587
4588         /* If we respond to a enum_printers level 1 on our name with flags
4589            set to PRINTER_ENUM_REMOTE with a list of printers then these
4590            printers incorrectly appear in the APW browse list.
4591            Specifically the printers for the server appear at the workgroup
4592            level where all the other servers in the domain are
4593            listed. Windows responds to this call with a
4594            WERR_CAN_NOT_COMPLETE so we should do the same. */
4595
4596         if (name[0] == '\\' && name[1] == '\\') {
4597                  s = name + 2;
4598         }
4599
4600         if (is_myname_or_ipaddr(s)) {
4601                  return WERR_CAN_NOT_COMPLETE;
4602         }
4603
4604         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4605 }
4606
4607 /********************************************************************
4608  * api_spoolss_enumprinters
4609  *
4610  * called from api_spoolss_enumprinters (see this to understand)
4611  ********************************************************************/
4612
4613 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4614                                        union spoolss_PrinterInfo **info_p,
4615                                        uint32_t *count)
4616 {
4617         int snum;
4618         int n_services = lp_numservices();
4619         union spoolss_PrinterInfo *info = NULL;
4620         WERROR result = WERR_OK;
4621
4622         *count = 0;
4623
4624         for (snum=0; snum<n_services; snum++) {
4625
4626                 struct spoolss_PrinterInfo2 info2;
4627                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4628
4629                 if (!snum_is_shared_printer(snum)) {
4630                         continue;
4631                 }
4632
4633                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4634
4635                 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4636                 if (!W_ERROR_IS_OK(result)) {
4637                         continue;
4638                 }
4639
4640                 result = construct_printer_info2(info, ntprinter, &info2, snum);
4641                 free_a_printer(&ntprinter, 2);
4642                 if (!W_ERROR_IS_OK(result)) {
4643                         continue;
4644                 }
4645
4646                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4647                                             union spoolss_PrinterInfo,
4648                                             *count + 1);
4649                 if (!info) {
4650                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4651                         result = WERR_NOMEM;
4652                         goto out;
4653                 }
4654
4655                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4656
4657                 info[*count].info2 = info2;
4658
4659                 (*count)++;
4660         }
4661
4662  out:
4663         if (!W_ERROR_IS_OK(result)) {
4664                 TALLOC_FREE(info);
4665                 *count = 0;
4666                 return result;
4667         }
4668
4669         *info_p = info;
4670
4671         return WERR_OK;
4672 }
4673
4674 /********************************************************************
4675  * handle enumeration of printers at level 1
4676  ********************************************************************/
4677
4678 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4679                                   uint32_t flags,
4680                                   const char *name,
4681                                   union spoolss_PrinterInfo **info,
4682                                   uint32_t *count)
4683 {
4684         /* Not all the flags are equals */
4685
4686         if (flags & PRINTER_ENUM_LOCAL) {
4687                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4688         }
4689
4690         if (flags & PRINTER_ENUM_NAME) {
4691                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4692         }
4693
4694 #if 0   /* JERRY - disabled for now */
4695         if (flags & PRINTER_ENUM_REMOTE) {
4696                 return enum_all_printers_info_1_remote(mem_ctx, name, info, count);
4697         }
4698 #endif
4699
4700         if (flags & PRINTER_ENUM_NETWORK) {
4701                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4702         }
4703
4704         return WERR_OK; /* NT4sp5 does that */
4705 }
4706
4707 /********************************************************************
4708  * handle enumeration of printers at level 2
4709  ********************************************************************/
4710
4711 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4712                                   uint32_t flags,
4713                                   const char *servername,
4714                                   union spoolss_PrinterInfo **info,
4715                                   uint32_t *count)
4716 {
4717         if (flags & PRINTER_ENUM_LOCAL) {
4718                 return enum_all_printers_info_2(mem_ctx, info, count);
4719         }
4720
4721         if (flags & PRINTER_ENUM_NAME) {
4722                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4723                         return WERR_INVALID_NAME;
4724                 }
4725
4726                 return enum_all_printers_info_2(mem_ctx, info, count);
4727         }
4728
4729         if (flags & PRINTER_ENUM_REMOTE) {
4730                 return WERR_UNKNOWN_LEVEL;
4731         }
4732
4733         return WERR_OK;
4734 }
4735
4736 /********************************************************************
4737  * handle enumeration of printers at level 5
4738  ********************************************************************/
4739
4740 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4741                                   uint32_t flags,
4742                                   const char *servername,
4743                                   union spoolss_PrinterInfo **info,
4744                                   uint32_t *count)
4745 {
4746 /*      return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4747         return WERR_OK;
4748 }
4749
4750 /****************************************************************
4751  _spoolss_EnumPrinters
4752 ****************************************************************/
4753
4754 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4755                              struct spoolss_EnumPrinters *r)
4756 {
4757         const char *name;
4758         WERROR result;
4759
4760         /* that's an [in out] buffer */
4761
4762         if (!r->in.buffer && (r->in.offered != 0)) {
4763                 return WERR_INVALID_PARAM;
4764         }
4765
4766         DEBUG(4,("_spoolss_EnumPrinters\n"));
4767
4768         *r->out.needed = 0;
4769         *r->out.count = 0;
4770         *r->out.info = NULL;
4771
4772         /*
4773          * Level 1:
4774          *          flags==PRINTER_ENUM_NAME
4775          *           if name=="" then enumerates all printers
4776          *           if name!="" then enumerate the printer
4777          *          flags==PRINTER_ENUM_REMOTE
4778          *          name is NULL, enumerate printers
4779          * Level 2: name!="" enumerates printers, name can't be NULL
4780          * Level 3: doesn't exist
4781          * Level 4: does a local registry lookup
4782          * Level 5: same as Level 2
4783          */
4784
4785         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4786         W_ERROR_HAVE_NO_MEMORY(name);
4787
4788         switch (r->in.level) {
4789         case 1:
4790                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4791                                              r->out.info, r->out.count);
4792                 break;
4793         case 2:
4794                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4795                                              r->out.info, r->out.count);
4796                 break;
4797         case 5:
4798                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4799                                              r->out.info, r->out.count);
4800                 break;
4801         case 3:
4802         case 4:
4803                 result = WERR_OK; /* ??? */
4804                 break;
4805         default:
4806                 return WERR_UNKNOWN_LEVEL;
4807         }
4808
4809         if (!W_ERROR_IS_OK(result)) {
4810                 return result;
4811         }
4812
4813         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4814                                                      spoolss_EnumPrinters, NULL,
4815                                                      *r->out.info, r->in.level,
4816                                                      *r->out.count);
4817         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4818         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4819
4820         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4821 }
4822
4823 /****************************************************************
4824  _spoolss_GetPrinter
4825 ****************************************************************/
4826
4827 WERROR _spoolss_GetPrinter(pipes_struct *p,
4828                            struct spoolss_GetPrinter *r)
4829 {
4830         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4831         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4832         WERROR result = WERR_OK;
4833
4834         int snum;
4835
4836         /* that's an [in out] buffer */
4837
4838         if (!r->in.buffer && (r->in.offered != 0)) {
4839                 return WERR_INVALID_PARAM;
4840         }
4841
4842         *r->out.needed = 0;
4843
4844         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4845                 return WERR_BADFID;
4846         }
4847
4848         result = get_a_printer(Printer, &ntprinter, 2,
4849                                lp_const_servicename(snum));
4850         if (!W_ERROR_IS_OK(result)) {
4851                 return result;
4852         }
4853
4854         switch (r->in.level) {
4855         case 0:
4856                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4857                                                  &r->out.info->info0, snum);
4858                 break;
4859         case 1:
4860                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4861                                                  PRINTER_ENUM_ICON8,
4862                                                  &r->out.info->info1, snum);
4863                 break;
4864         case 2:
4865                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4866                                                  &r->out.info->info2, snum);
4867                 break;
4868         case 3:
4869                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4870                                                  &r->out.info->info3, snum);
4871                 break;
4872         case 4:
4873                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4874                                                  &r->out.info->info4, snum);
4875                 break;
4876         case 5:
4877                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4878                                                  &r->out.info->info5, snum);
4879                 break;
4880         case 6:
4881                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4882                                                  &r->out.info->info6, snum);
4883                 break;
4884         case 7:
4885                 result = construct_printer_info7(p->mem_ctx, Printer,
4886                                                  &r->out.info->info7, snum);
4887                 break;
4888         default:
4889                 result = WERR_UNKNOWN_LEVEL;
4890                 break;
4891         }
4892
4893         free_a_printer(&ntprinter, 2);
4894
4895         if (!W_ERROR_IS_OK(result)) {
4896                 TALLOC_FREE(r->out.info);
4897                 return result;
4898         }
4899
4900         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4901                                                r->out.info, r->in.level);
4902         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4903
4904         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4905 }
4906
4907 /********************************************************************
4908  ********************************************************************/
4909
4910 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4911                                                   fstring *fstring_array,
4912                                                   const char *cservername)
4913 {
4914         int i, num_strings = 0;
4915         const char **array = NULL;
4916
4917         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4918
4919                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4920                                                   cservername, fstring_array[i]);
4921                 if (!str) {
4922                         TALLOC_FREE(array);
4923                         return NULL;
4924                 }
4925
4926
4927                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4928                         TALLOC_FREE(array);
4929                         return NULL;
4930                 }
4931         }
4932
4933         if (i > 0) {
4934                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4935                              &array, &num_strings);
4936         }
4937
4938         return array;
4939 }
4940
4941 /********************************************************************
4942  * fill a spoolss_DriverInfo1 struct
4943  ********************************************************************/
4944
4945 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4946                                         struct spoolss_DriverInfo1 *r,
4947                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4948                                         const char *servername,
4949                                         const char *architecture)
4950 {
4951         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4952         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4953
4954         return WERR_OK;
4955 }
4956
4957 /********************************************************************
4958  * fill a spoolss_DriverInfo2 struct
4959  ********************************************************************/
4960
4961 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4962                                         struct spoolss_DriverInfo2 *r,
4963                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4964                                         const char *servername)
4965
4966 {
4967         const char *cservername = canon_servername(servername);
4968
4969         r->version              = driver->info_3->cversion;
4970
4971         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4972         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4973         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4974         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4975
4976         if (strlen(driver->info_3->driverpath)) {
4977                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4978                                 cservername, driver->info_3->driverpath);
4979         } else {
4980                 r->driver_path  = talloc_strdup(mem_ctx, "");
4981         }
4982         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4983
4984         if (strlen(driver->info_3->datafile)) {
4985                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4986                                 cservername, driver->info_3->datafile);
4987         } else {
4988                 r->data_file    = talloc_strdup(mem_ctx, "");
4989         }
4990         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4991
4992         if (strlen(driver->info_3->configfile)) {
4993                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4994                                 cservername, driver->info_3->configfile);
4995         } else {
4996                 r->config_file  = talloc_strdup(mem_ctx, "");
4997         }
4998         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4999
5000         return WERR_OK;
5001 }
5002
5003 /********************************************************************
5004  * fill a spoolss_DriverInfo3 struct
5005  ********************************************************************/
5006
5007 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5008                                         struct spoolss_DriverInfo3 *r,
5009                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5010                                         const char *servername)
5011 {
5012         const char *cservername = canon_servername(servername);
5013
5014         r->version              = driver->info_3->cversion;
5015
5016         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5017         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5018         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5019         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5020
5021         if (strlen(driver->info_3->driverpath)) {
5022                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5023                                 cservername, driver->info_3->driverpath);
5024         } else {
5025                 r->driver_path  = talloc_strdup(mem_ctx, "");
5026         }
5027         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5028
5029         if (strlen(driver->info_3->datafile)) {
5030                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5031                                 cservername, driver->info_3->datafile);
5032         } else {
5033                 r->data_file    = talloc_strdup(mem_ctx, "");
5034         }
5035         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5036
5037         if (strlen(driver->info_3->configfile)) {
5038                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5039                                 cservername, driver->info_3->configfile);
5040         } else {
5041                 r->config_file  = talloc_strdup(mem_ctx, "");
5042         }
5043         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5044
5045         if (strlen(driver->info_3->helpfile)) {
5046                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5047                                 cservername, driver->info_3->helpfile);
5048         } else {
5049                 r->help_file    = talloc_strdup(mem_ctx, "");
5050         }
5051         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5052
5053         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5054         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5055         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5056         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5057
5058         r->dependent_files = string_array_from_driver_info(mem_ctx,
5059                                                            driver->info_3->dependentfiles,
5060                                                            cservername);
5061         return WERR_OK;
5062 }
5063
5064 /********************************************************************
5065  * fill a spoolss_DriverInfo6 struct
5066  ********************************************************************/
5067
5068 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5069                                         struct spoolss_DriverInfo6 *r,
5070                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5071                                         const char *servername)
5072 {
5073         const char *cservername = canon_servername(servername);
5074
5075         r->version              = driver->info_3->cversion;
5076
5077         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5078         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5079         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5080         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5081
5082         if (strlen(driver->info_3->driverpath)) {
5083                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5084                                 cservername, driver->info_3->driverpath);
5085         } else {
5086                 r->driver_path  = talloc_strdup(mem_ctx, "");
5087         }
5088         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5089
5090         if (strlen(driver->info_3->datafile)) {
5091                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5092                                 cservername, driver->info_3->datafile);
5093         } else {
5094                 r->data_file    = talloc_strdup(mem_ctx, "");
5095         }
5096         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5097
5098         if (strlen(driver->info_3->configfile)) {
5099                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5100                                 cservername, driver->info_3->configfile);
5101         } else {
5102                 r->config_file  = talloc_strdup(mem_ctx, "");
5103         }
5104         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5105
5106         if (strlen(driver->info_3->helpfile)) {
5107                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5108                                 cservername, driver->info_3->helpfile);
5109         } else {
5110                 r->help_file    = talloc_strdup(mem_ctx, "");
5111         }
5112         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5113
5114         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5115         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5116         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5117         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5118
5119         r->dependent_files = string_array_from_driver_info(mem_ctx,
5120                                                            driver->info_3->dependentfiles,
5121                                                            cservername);
5122         r->previous_names = string_array_from_driver_info(mem_ctx,
5123                                                           NULL,
5124                                                           cservername);
5125
5126         r->driver_date          = 0;
5127         r->driver_version       = 0;
5128
5129         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5130         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5131         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5132         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5133         r->hardware_id          = talloc_strdup(mem_ctx, "");
5134         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5135         r->provider             = talloc_strdup(mem_ctx, "");
5136         W_ERROR_HAVE_NO_MEMORY(r->provider);
5137
5138         return WERR_OK;
5139 }
5140
5141 /********************************************************************
5142  * construct_printer_driver_info_1
5143  ********************************************************************/
5144
5145 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5146                                               struct spoolss_DriverInfo1 *r,
5147                                               int snum,
5148                                               const char *servername,
5149                                               const char *architecture,
5150                                               uint32_t version)
5151 {
5152         NT_PRINTER_INFO_LEVEL *printer = NULL;
5153         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5154         WERROR result;
5155
5156         ZERO_STRUCT(driver);
5157
5158         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5159                 return WERR_INVALID_PRINTER_NAME;
5160
5161         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5162                 free_a_printer(&printer, 2);
5163                 return WERR_UNKNOWN_PRINTER_DRIVER;
5164         }
5165
5166         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5167
5168         free_a_printer(&printer,2);
5169
5170         return result;
5171 }
5172
5173 /********************************************************************
5174  * construct_printer_driver_info_2
5175  * fill a printer_info_2 struct
5176  ********************************************************************/
5177
5178 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5179                                               struct spoolss_DriverInfo2 *r,
5180                                               int snum,
5181                                               const char *servername,
5182                                               const char *architecture,
5183                                               uint32_t version)
5184 {
5185         NT_PRINTER_INFO_LEVEL *printer = NULL;
5186         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5187         WERROR result;
5188
5189         ZERO_STRUCT(printer);
5190         ZERO_STRUCT(driver);
5191
5192         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5193                 return WERR_INVALID_PRINTER_NAME;
5194
5195         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5196                 free_a_printer(&printer, 2);
5197                 return WERR_UNKNOWN_PRINTER_DRIVER;
5198         }
5199
5200         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5201
5202         free_a_printer(&printer,2);
5203
5204         return result;
5205 }
5206
5207 /********************************************************************
5208  * copy a strings array and convert to UNICODE
5209  *
5210  * convert an array of ascii string to a UNICODE string
5211  ********************************************************************/
5212
5213 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5214 {
5215         int i=0;
5216         int j=0;
5217         const char *v;
5218         char *line = NULL;
5219         TALLOC_CTX *ctx = talloc_tos();
5220
5221         DEBUG(6,("init_unistr_array\n"));
5222         *uni_array=NULL;
5223
5224         while (true) {
5225                 if ( !char_array ) {
5226                         v = "";
5227                 } else {
5228                         v = char_array[i];
5229                         if (!v)
5230                                 v = ""; /* hack to handle null lists */
5231                 }
5232
5233                 /* hack to allow this to be used in places other than when generating
5234                    the list of dependent files */
5235
5236                 TALLOC_FREE(line);
5237                 if ( servername ) {
5238                         line = talloc_asprintf(ctx,
5239                                         "\\\\%s%s",
5240                                         canon_servername(servername),
5241                                         v);
5242                 } else {
5243                         line = talloc_strdup(ctx, v);
5244                 }
5245
5246                 if (!line) {
5247                         SAFE_FREE(*uni_array);
5248                         return 0;
5249                 }
5250                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5251
5252                 /* add one extra unit16 for the second terminating NULL */
5253
5254                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5255                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5256                         return 0;
5257                 }
5258
5259                 if ( !strlen(v) )
5260                         break;
5261
5262                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5263                 i++;
5264         }
5265
5266         if (*uni_array) {
5267                 /* special case for ""; we need to add both NULL's here */
5268                 if (!j)
5269                         (*uni_array)[j++]=0x0000;
5270                 (*uni_array)[j]=0x0000;
5271         }
5272
5273         DEBUGADD(6,("last one:done\n"));
5274
5275         /* return size of array in uint16's */
5276
5277         return j+1;
5278 }
5279
5280 /********************************************************************
5281  * construct_printer_info_3
5282  * fill a printer_info_3 struct
5283  ********************************************************************/
5284
5285 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5286                                               struct spoolss_DriverInfo3 *r,
5287                                               int snum,
5288                                               const char *servername,
5289                                               const char *architecture,
5290                                               uint32_t version)
5291 {
5292         NT_PRINTER_INFO_LEVEL *printer = NULL;
5293         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5294         WERROR status;
5295         ZERO_STRUCT(driver);
5296
5297         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5298         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5299         if (!W_ERROR_IS_OK(status))
5300                 return WERR_INVALID_PRINTER_NAME;
5301
5302         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5303         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5304
5305 #if 0   /* JERRY */
5306
5307         /*
5308          * I put this code in during testing.  Helpful when commenting out the
5309          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5310          * as win2k always queries the driver using an infor level of 6.
5311          * I've left it in (but ifdef'd out) because I'll probably
5312          * use it in experimentation again in the future.   --jerry 22/01/2002
5313          */
5314
5315         if (!W_ERROR_IS_OK(status)) {
5316                 /*
5317                  * Is this a W2k client ?
5318                  */
5319                 if (version == 3) {
5320                         /* Yes - try again with a WinNT driver. */
5321                         version = 2;
5322                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5323                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5324                 }
5325 #endif
5326
5327                 if (!W_ERROR_IS_OK(status)) {
5328                         free_a_printer(&printer,2);
5329                         return WERR_UNKNOWN_PRINTER_DRIVER;
5330                 }
5331
5332 #if 0   /* JERRY */
5333         }
5334 #endif
5335
5336
5337         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5338
5339         free_a_printer(&printer,2);
5340
5341         return status;
5342 }
5343
5344 /********************************************************************
5345  * construct_printer_info_6
5346  * fill a printer_info_6 struct
5347  ********************************************************************/
5348
5349 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5350                                               struct spoolss_DriverInfo6 *r,
5351                                               int snum,
5352                                               const char *servername,
5353                                               const char *architecture,
5354                                               uint32_t version)
5355 {
5356         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5357         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5358         WERROR                          status;
5359
5360         ZERO_STRUCT(driver);
5361
5362         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5363
5364         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5365
5366         if (!W_ERROR_IS_OK(status))
5367                 return WERR_INVALID_PRINTER_NAME;
5368
5369         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5370
5371         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5372
5373         if (!W_ERROR_IS_OK(status))
5374         {
5375                 /*
5376                  * Is this a W2k client ?
5377                  */
5378
5379                 if (version < 3) {
5380                         free_a_printer(&printer,2);
5381                         return WERR_UNKNOWN_PRINTER_DRIVER;
5382                 }
5383
5384                 /* Yes - try again with a WinNT driver. */
5385                 version = 2;
5386                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5387                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5388                 if (!W_ERROR_IS_OK(status)) {
5389                         free_a_printer(&printer,2);
5390                         return WERR_UNKNOWN_PRINTER_DRIVER;
5391                 }
5392         }
5393
5394         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5395
5396         free_a_printer(&printer,2);
5397         free_a_printer_driver(driver, 3);
5398
5399         return status;
5400 }
5401
5402 /****************************************************************
5403  _spoolss_GetPrinterDriver2
5404 ****************************************************************/
5405
5406 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5407                                   struct spoolss_GetPrinterDriver2 *r)
5408 {
5409         Printer_entry *printer;
5410         WERROR result;
5411
5412         const char *servername;
5413         int snum;
5414
5415         /* that's an [in out] buffer */
5416
5417         if (!r->in.buffer && (r->in.offered != 0)) {
5418                 return WERR_INVALID_PARAM;
5419         }
5420
5421         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5422
5423         if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5424                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5425                 return WERR_INVALID_PRINTER_NAME;
5426         }
5427
5428         *r->out.needed = 0;
5429         *r->out.server_major_version = 0;
5430         *r->out.server_minor_version = 0;
5431
5432         servername = get_server_name(printer);
5433
5434         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5435                 return WERR_BADFID;
5436         }
5437
5438         switch (r->in.level) {
5439         case 1:
5440                 result = construct_printer_driver_info_1(p->mem_ctx,
5441                                                          &r->out.info->info1,
5442                                                          snum,
5443                                                          servername,
5444                                                          r->in.architecture,
5445                                                          r->in.client_major_version);
5446                 break;
5447         case 2:
5448                 result = construct_printer_driver_info_2(p->mem_ctx,
5449                                                          &r->out.info->info2,
5450                                                          snum,
5451                                                          servername,
5452                                                          r->in.architecture,
5453                                                          r->in.client_major_version);
5454                 break;
5455         case 3:
5456                 result = construct_printer_driver_info_3(p->mem_ctx,
5457                                                          &r->out.info->info3,
5458                                                          snum,
5459                                                          servername,
5460                                                          r->in.architecture,
5461                                                          r->in.client_major_version);
5462                 break;
5463         case 6:
5464                 result = construct_printer_driver_info_6(p->mem_ctx,
5465                                                          &r->out.info->info6,
5466                                                          snum,
5467                                                          servername,
5468                                                          r->in.architecture,
5469                                                          r->in.client_major_version);
5470                 break;
5471         default:
5472 #if 0   /* JERRY */
5473         case 101:
5474                 /* apparently this call is the equivalent of
5475                    EnumPrinterDataEx() for the DsDriver key */
5476                 break;
5477 #endif
5478                 result = WERR_UNKNOWN_LEVEL;
5479                 break;
5480         }
5481
5482         if (!W_ERROR_IS_OK(result)) {
5483                 TALLOC_FREE(r->out.info);
5484                 return result;
5485         }
5486
5487         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5488                                                r->out.info, r->in.level);
5489         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5490
5491         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5492 }
5493
5494
5495 /****************************************************************
5496  _spoolss_StartPagePrinter
5497 ****************************************************************/
5498
5499 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5500                                  struct spoolss_StartPagePrinter *r)
5501 {
5502         POLICY_HND *handle = r->in.handle;
5503
5504         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5505
5506         if (!Printer) {
5507                 DEBUG(3,("_spoolss_StartPagePrinter: "
5508                         "Error in startpageprinter printer handle\n"));
5509                 return WERR_BADFID;
5510         }
5511
5512         Printer->page_started=True;
5513         return WERR_OK;
5514 }
5515
5516 /****************************************************************
5517  _spoolss_EndPagePrinter
5518 ****************************************************************/
5519
5520 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5521                                struct spoolss_EndPagePrinter *r)
5522 {
5523         POLICY_HND *handle = r->in.handle;
5524         int snum;
5525
5526         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5527
5528         if (!Printer) {
5529                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5530                         OUR_HANDLE(handle)));
5531                 return WERR_BADFID;
5532         }
5533
5534         if (!get_printer_snum(p, handle, &snum, NULL))
5535                 return WERR_BADFID;
5536
5537         Printer->page_started=False;
5538         print_job_endpage(snum, Printer->jobid);
5539
5540         return WERR_OK;
5541 }
5542
5543 /****************************************************************
5544  _spoolss_StartDocPrinter
5545 ****************************************************************/
5546
5547 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5548                                 struct spoolss_StartDocPrinter *r)
5549 {
5550         POLICY_HND *handle = r->in.handle;
5551         uint32_t *jobid = r->out.job_id;
5552         struct spoolss_DocumentInfo1 *info_1;
5553         int snum;
5554         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5555
5556         if (!Printer) {
5557                 DEBUG(2,("_spoolss_StartDocPrinter: "
5558                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5559                 return WERR_BADFID;
5560         }
5561
5562         if (r->in.level != 1) {
5563                 return WERR_UNKNOWN_LEVEL;
5564         }
5565
5566         info_1 = r->in.info.info1;
5567
5568         /*
5569          * a nice thing with NT is it doesn't listen to what you tell it.
5570          * when asked to send _only_ RAW datas, it tries to send datas
5571          * in EMF format.
5572          *
5573          * So I add checks like in NT Server ...
5574          */
5575
5576         if (info_1->datatype) {
5577                 if (strcmp(info_1->datatype, "RAW") != 0) {
5578                         (*jobid)=0;
5579                         return WERR_INVALID_DATATYPE;
5580                 }
5581         }
5582
5583         /* get the share number of the printer */
5584         if (!get_printer_snum(p, handle, &snum, NULL)) {
5585                 return WERR_BADFID;
5586         }
5587
5588         Printer->jobid = print_job_start(p->server_info, snum,
5589                                          info_1->document_name,
5590                                          Printer->nt_devmode);
5591
5592         /* An error occured in print_job_start() so return an appropriate
5593            NT error code. */
5594
5595         if (Printer->jobid == -1) {
5596                 return map_werror_from_unix(errno);
5597         }
5598
5599         Printer->document_started=True;
5600         (*jobid) = Printer->jobid;
5601
5602         return WERR_OK;
5603 }
5604
5605 /****************************************************************
5606  _spoolss_EndDocPrinter
5607 ****************************************************************/
5608
5609 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5610                               struct spoolss_EndDocPrinter *r)
5611 {
5612         POLICY_HND *handle = r->in.handle;
5613
5614         return _spoolss_enddocprinter_internal(p, handle);
5615 }
5616
5617 /****************************************************************
5618  _spoolss_WritePrinter
5619 ****************************************************************/
5620
5621 WERROR _spoolss_WritePrinter(pipes_struct *p,
5622                              struct spoolss_WritePrinter *r)
5623 {
5624         POLICY_HND *handle = r->in.handle;
5625         uint32 buffer_size = r->in._data_size;
5626         uint8 *buffer = r->in.data.data;
5627         uint32 *buffer_written = &r->in._data_size;
5628         int snum;
5629         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5630
5631         if (!Printer) {
5632                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5633                         OUR_HANDLE(handle)));
5634                 *r->out.num_written = r->in._data_size;
5635                 return WERR_BADFID;
5636         }
5637
5638         if (!get_printer_snum(p, handle, &snum, NULL))
5639                 return WERR_BADFID;
5640
5641         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5642                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5643         if (*buffer_written == (uint32)-1) {
5644                 *r->out.num_written = 0;
5645                 if (errno == ENOSPC)
5646                         return WERR_NO_SPOOL_SPACE;
5647                 else
5648                         return WERR_ACCESS_DENIED;
5649         }
5650
5651         *r->out.num_written = r->in._data_size;
5652
5653         return WERR_OK;
5654 }
5655
5656 /********************************************************************
5657  * api_spoolss_getprinter
5658  * called from the spoolss dispatcher
5659  *
5660  ********************************************************************/
5661
5662 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5663                               pipes_struct *p)
5664 {
5665         int snum;
5666         WERROR errcode = WERR_BADFUNC;
5667         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5668
5669         if (!Printer) {
5670                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5671                 return WERR_BADFID;
5672         }
5673
5674         if (!get_printer_snum(p, handle, &snum, NULL))
5675                 return WERR_BADFID;
5676
5677         switch (command) {
5678         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5679                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5680                         errcode = WERR_OK;
5681                 }
5682                 break;
5683         case SPOOLSS_PRINTER_CONTROL_RESUME:
5684         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5685                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5686                         errcode = WERR_OK;
5687                 }
5688                 break;
5689         case SPOOLSS_PRINTER_CONTROL_PURGE:
5690                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5691                         errcode = WERR_OK;
5692                 }
5693                 break;
5694         default:
5695                 return WERR_UNKNOWN_LEVEL;
5696         }
5697
5698         return errcode;
5699 }
5700
5701
5702 /****************************************************************
5703  _spoolss_AbortPrinter
5704  * From MSDN: "Deletes printer's spool file if printer is configured
5705  * for spooling"
5706 ****************************************************************/
5707
5708 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5709                              struct spoolss_AbortPrinter *r)
5710 {
5711         POLICY_HND      *handle = r->in.handle;
5712         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5713         int             snum;
5714         WERROR          errcode = WERR_OK;
5715
5716         if (!Printer) {
5717                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5718                         OUR_HANDLE(handle)));
5719                 return WERR_BADFID;
5720         }
5721
5722         if (!get_printer_snum(p, handle, &snum, NULL))
5723                 return WERR_BADFID;
5724
5725         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5726
5727         return errcode;
5728 }
5729
5730 /********************************************************************
5731  * called by spoolss_api_setprinter
5732  * when updating a printer description
5733  ********************************************************************/
5734
5735 static WERROR update_printer_sec(POLICY_HND *handle,
5736                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5737 {
5738         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5739         WERROR result;
5740         int snum;
5741
5742         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5743
5744         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5745                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5746                          OUR_HANDLE(handle)));
5747
5748                 result = WERR_BADFID;
5749                 goto done;
5750         }
5751
5752         if (!secdesc_ctr) {
5753                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5754                 result = WERR_INVALID_PARAM;
5755                 goto done;
5756         }
5757
5758         /* Check the user has permissions to change the security
5759            descriptor.  By experimentation with two NT machines, the user
5760            requires Full Access to the printer to change security
5761            information. */
5762
5763         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5764                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5765                 result = WERR_ACCESS_DENIED;
5766                 goto done;
5767         }
5768
5769         /* NT seems to like setting the security descriptor even though
5770            nothing may have actually changed. */
5771
5772         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5773                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5774                 result = WERR_BADFID;
5775                 goto done;
5776         }
5777
5778         if (DEBUGLEVEL >= 10) {
5779                 SEC_ACL *the_acl;
5780                 int i;
5781
5782                 the_acl = old_secdesc_ctr->sd->dacl;
5783                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5784                            PRINTERNAME(snum), the_acl->num_aces));
5785
5786                 for (i = 0; i < the_acl->num_aces; i++) {
5787                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5788                                            &the_acl->aces[i].trustee),
5789                                   the_acl->aces[i].access_mask));
5790                 }
5791
5792                 the_acl = secdesc_ctr->sd->dacl;
5793
5794                 if (the_acl) {
5795                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5796                                    PRINTERNAME(snum), the_acl->num_aces));
5797
5798                         for (i = 0; i < the_acl->num_aces; i++) {
5799                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5800                                                    &the_acl->aces[i].trustee),
5801                                            the_acl->aces[i].access_mask));
5802                         }
5803                 } else {
5804                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5805                 }
5806         }
5807
5808         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5809         if (!new_secdesc_ctr) {
5810                 result = WERR_NOMEM;
5811                 goto done;
5812         }
5813
5814         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5815                 result = WERR_OK;
5816                 goto done;
5817         }
5818
5819         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5820
5821  done:
5822
5823         return result;
5824 }
5825
5826 /********************************************************************
5827  Canonicalize printer info from a client
5828
5829  ATTN: It does not matter what we set the servername to hear
5830  since we do the necessary work in get_a_printer() to set it to
5831  the correct value based on what the client sent in the
5832  _spoolss_open_printer_ex().
5833  ********************************************************************/
5834
5835 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5836 {
5837         fstring printername;
5838         const char *p;
5839
5840         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5841                 "portname=%s drivername=%s comment=%s location=%s\n",
5842                 info->servername, info->printername, info->sharename,
5843                 info->portname, info->drivername, info->comment, info->location));
5844
5845         /* we force some elements to "correct" values */
5846         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5847         fstrcpy(info->sharename, lp_servicename(snum));
5848
5849         /* check to see if we allow printername != sharename */
5850
5851         if ( lp_force_printername(snum) ) {
5852                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5853                         global_myname(), info->sharename );
5854         } else {
5855
5856                 /* make sure printername is in \\server\printername format */
5857
5858                 fstrcpy( printername, info->printername );
5859                 p = printername;
5860                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5861                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5862                                 p++;
5863                 }
5864
5865                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5866                          global_myname(), p );
5867         }
5868
5869         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5870         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5871
5872
5873
5874         return True;
5875 }
5876
5877 /****************************************************************************
5878 ****************************************************************************/
5879
5880 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5881 {
5882         char *cmd = lp_addport_cmd();
5883         char *command = NULL;
5884         int ret;
5885         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5886         bool is_print_op = False;
5887
5888         if ( !*cmd ) {
5889                 return WERR_ACCESS_DENIED;
5890         }
5891
5892         command = talloc_asprintf(ctx,
5893                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5894         if (!command) {
5895                 return WERR_NOMEM;
5896         }
5897
5898         if ( token )
5899                 is_print_op = user_has_privileges( token, &se_printop );
5900
5901         DEBUG(10,("Running [%s]\n", command));
5902
5903         /********* BEGIN SePrintOperatorPrivilege **********/
5904
5905         if ( is_print_op )
5906                 become_root();
5907
5908         ret = smbrun(command, NULL);
5909
5910         if ( is_print_op )
5911                 unbecome_root();
5912
5913         /********* END SePrintOperatorPrivilege **********/
5914
5915         DEBUGADD(10,("returned [%d]\n", ret));
5916
5917         TALLOC_FREE(command);
5918
5919         if ( ret != 0 ) {
5920                 return WERR_ACCESS_DENIED;
5921         }
5922
5923         return WERR_OK;
5924 }
5925
5926 /****************************************************************************
5927 ****************************************************************************/
5928
5929 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5930 {
5931         char *cmd = lp_addprinter_cmd();
5932         char **qlines;
5933         char *command = NULL;
5934         int numlines;
5935         int ret;
5936         int fd;
5937         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5938         bool is_print_op = False;
5939         char *remote_machine = talloc_strdup(ctx, "%m");
5940
5941         if (!remote_machine) {
5942                 return false;
5943         }
5944         remote_machine = talloc_sub_basic(ctx,
5945                                 current_user_info.smb_name,
5946                                 current_user_info.domain,
5947                                 remote_machine);
5948         if (!remote_machine) {
5949                 return false;
5950         }
5951
5952         command = talloc_asprintf(ctx,
5953                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5954                         cmd, printer->info_2->printername, printer->info_2->sharename,
5955                         printer->info_2->portname, printer->info_2->drivername,
5956                         printer->info_2->location, printer->info_2->comment, remote_machine);
5957         if (!command) {
5958                 return false;
5959         }
5960
5961         if ( token )
5962                 is_print_op = user_has_privileges( token, &se_printop );
5963
5964         DEBUG(10,("Running [%s]\n", command));
5965
5966         /********* BEGIN SePrintOperatorPrivilege **********/
5967
5968         if ( is_print_op )
5969                 become_root();
5970
5971         if ( (ret = smbrun(command, &fd)) == 0 ) {
5972                 /* Tell everyone we updated smb.conf. */
5973                 message_send_all(smbd_messaging_context(),
5974                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5975         }
5976
5977         if ( is_print_op )
5978                 unbecome_root();
5979
5980         /********* END SePrintOperatorPrivilege **********/
5981
5982         DEBUGADD(10,("returned [%d]\n", ret));
5983
5984         TALLOC_FREE(command);
5985         TALLOC_FREE(remote_machine);
5986
5987         if ( ret != 0 ) {
5988                 if (fd != -1)
5989                         close(fd);
5990                 return False;
5991         }
5992
5993         /* reload our services immediately */
5994         reload_services( False );
5995
5996         numlines = 0;
5997         /* Get lines and convert them back to dos-codepage */
5998         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5999         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6000         close(fd);
6001
6002         /* Set the portname to what the script says the portname should be. */
6003         /* but don't require anything to be return from the script exit a good error code */
6004
6005         if (numlines) {
6006                 /* Set the portname to what the script says the portname should be. */
6007                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6008                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6009         }
6010
6011         TALLOC_FREE(qlines);
6012         return True;
6013 }
6014
6015
6016 /********************************************************************
6017  * Called by spoolss_api_setprinter
6018  * when updating a printer description.
6019  ********************************************************************/
6020
6021 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6022                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6023                              struct spoolss_DeviceMode *devmode)
6024 {
6025         int snum;
6026         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6027         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6028         WERROR result;
6029         UNISTR2 buffer;
6030         fstring asc_buffer;
6031
6032         DEBUG(8,("update_printer\n"));
6033
6034         result = WERR_OK;
6035
6036         if (!Printer) {
6037                 result = WERR_BADFID;
6038                 goto done;
6039         }
6040
6041         if (!get_printer_snum(p, handle, &snum, NULL)) {
6042                 result = WERR_BADFID;
6043                 goto done;
6044         }
6045
6046         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6047             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6048                 result = WERR_BADFID;
6049                 goto done;
6050         }
6051
6052         DEBUGADD(8,("Converting info_2 struct\n"));
6053
6054         /*
6055          * convert_printer_info converts the incoming
6056          * info from the client and overwrites the info
6057          * just read from the tdb in the pointer 'printer'.
6058          */
6059
6060         if (!convert_printer_info_new(info_ctr, printer)) {
6061                 result =  WERR_NOMEM;
6062                 goto done;
6063         }
6064
6065         if (devmode) {
6066                 /* we have a valid devmode
6067                    convert it and link it*/
6068
6069                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6070                 if (!convert_devicemode_new(printer->info_2->printername,
6071                                             devmode,
6072                                             &printer->info_2->devmode)) {
6073                         result =  WERR_NOMEM;
6074                         goto done;
6075                 }
6076         }
6077
6078         /* Do sanity check on the requested changes for Samba */
6079
6080         if (!check_printer_ok(printer->info_2, snum)) {
6081                 result = WERR_INVALID_PARAM;
6082                 goto done;
6083         }
6084
6085         /* FIXME!!! If the driver has changed we really should verify that
6086            it is installed before doing much else   --jerry */
6087
6088         /* Check calling user has permission to update printer description */
6089
6090         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6091                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6092                 result = WERR_ACCESS_DENIED;
6093                 goto done;
6094         }
6095
6096         /* Call addprinter hook */
6097         /* Check changes to see if this is really needed */
6098
6099         if ( *lp_addprinter_cmd()
6100                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6101                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6102                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6103                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6104         {
6105                 /* add_printer_hook() will call reload_services() */
6106
6107                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6108                                        printer) ) {
6109                         result = WERR_ACCESS_DENIED;
6110                         goto done;
6111                 }
6112         }
6113
6114         /*
6115          * When a *new* driver is bound to a printer, the drivername is used to
6116          * lookup previously saved driver initialization info, which is then
6117          * bound to the printer, simulating what happens in the Windows arch.
6118          */
6119         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6120         {
6121                 if (!set_driver_init(printer, 2))
6122                 {
6123                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6124                                 printer->info_2->drivername));
6125                 }
6126
6127                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6128                         printer->info_2->drivername));
6129
6130                 notify_printer_driver(snum, printer->info_2->drivername);
6131         }
6132
6133         /*
6134          * flag which changes actually occured.  This is a small subset of
6135          * all the possible changes.  We also have to update things in the
6136          * DsSpooler key.
6137          */
6138
6139         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6140                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6141                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6142                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6143
6144                 notify_printer_comment(snum, printer->info_2->comment);
6145         }
6146
6147         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6148                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6149                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6150                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6151
6152                 notify_printer_sharename(snum, printer->info_2->sharename);
6153         }
6154
6155         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6156                 char *pname;
6157
6158                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6159                         pname++;
6160                 else
6161                         pname = printer->info_2->printername;
6162
6163
6164                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6165                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6166                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6167
6168                 notify_printer_printername( snum, pname );
6169         }
6170
6171         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6172                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6173                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6174                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6175
6176                 notify_printer_port(snum, printer->info_2->portname);
6177         }
6178
6179         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6180                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6181                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6182                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6183
6184                 notify_printer_location(snum, printer->info_2->location);
6185         }
6186
6187         /* here we need to update some more DsSpooler keys */
6188         /* uNCName, serverName, shortServerName */
6189
6190         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6191         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6192                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6193         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6194                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6195
6196         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6197                  global_myname(), printer->info_2->sharename );
6198         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6199         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6200                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6201
6202         /* Update printer info */
6203         result = mod_a_printer(printer, 2);
6204
6205 done:
6206         free_a_printer(&printer, 2);
6207         free_a_printer(&old_printer, 2);
6208
6209
6210         return result;
6211 }
6212
6213 /****************************************************************************
6214 ****************************************************************************/
6215 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6216                                            struct spoolss_SetPrinterInfo7 *info7)
6217 {
6218 #ifdef HAVE_ADS
6219         int snum;
6220         Printer_entry *Printer;
6221
6222         if ( lp_security() != SEC_ADS ) {
6223                 return WERR_UNKNOWN_LEVEL;
6224         }
6225
6226         Printer = find_printer_index_by_hnd(p, handle);
6227
6228         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6229
6230         if (!Printer)
6231                 return WERR_BADFID;
6232
6233         if (!get_printer_snum(p, handle, &snum, NULL))
6234                 return WERR_BADFID;
6235
6236         nt_printer_publish(Printer, snum, info7->action);
6237
6238         return WERR_OK;
6239 #else
6240         return WERR_UNKNOWN_LEVEL;
6241 #endif
6242 }
6243
6244 /****************************************************************
6245  _spoolss_SetPrinter
6246 ****************************************************************/
6247
6248 WERROR _spoolss_SetPrinter(pipes_struct *p,
6249                            struct spoolss_SetPrinter *r)
6250 {
6251         POLICY_HND *handle = r->in.handle;
6252         WERROR result;
6253
6254         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6255
6256         if (!Printer) {
6257                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6258                         OUR_HANDLE(handle)));
6259                 return WERR_BADFID;
6260         }
6261
6262         /* check the level */
6263         switch (r->in.info_ctr->level) {
6264                 case 0:
6265                         return control_printer(handle, r->in.command, p);
6266                 case 2:
6267                         result = update_printer(p, handle,
6268                                                 r->in.info_ctr,
6269                                                 r->in.devmode_ctr->devmode);
6270                         if (!W_ERROR_IS_OK(result))
6271                                 return result;
6272                         if (r->in.secdesc_ctr->sd)
6273                                 result = update_printer_sec(handle, p,
6274                                                             r->in.secdesc_ctr);
6275                         return result;
6276                 case 3:
6277                         return update_printer_sec(handle, p,
6278                                                   r->in.secdesc_ctr);
6279                 case 7:
6280                         return publish_or_unpublish_printer(p, handle,
6281                                                             r->in.info_ctr->info.info7);
6282                 default:
6283                         return WERR_UNKNOWN_LEVEL;
6284         }
6285 }
6286
6287 /****************************************************************
6288  _spoolss_FindClosePrinterNotify
6289 ****************************************************************/
6290
6291 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6292                                        struct spoolss_FindClosePrinterNotify *r)
6293 {
6294         POLICY_HND *handle = r->in.handle;
6295         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6296
6297         if (!Printer) {
6298                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6299                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6300                 return WERR_BADFID;
6301         }
6302
6303         if (Printer->notify.client_connected==True) {
6304                 int snum = -1;
6305
6306                 if ( Printer->printer_type == SPLHND_SERVER)
6307                         snum = -1;
6308                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6309                                 !get_printer_snum(p, handle, &snum, NULL) )
6310                         return WERR_BADFID;
6311
6312                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6313         }
6314
6315         Printer->notify.flags=0;
6316         Printer->notify.options=0;
6317         Printer->notify.localmachine[0]='\0';
6318         Printer->notify.printerlocal=0;
6319         TALLOC_FREE(Printer->notify.option);
6320         Printer->notify.client_connected=False;
6321
6322         return WERR_OK;
6323 }
6324
6325 /****************************************************************
6326  _spoolss_AddJob
6327 ****************************************************************/
6328
6329 WERROR _spoolss_AddJob(pipes_struct *p,
6330                        struct spoolss_AddJob *r)
6331 {
6332         if (!r->in.buffer && (r->in.offered != 0)) {
6333                 return WERR_INVALID_PARAM;
6334         }
6335
6336         /* this is what a NT server returns for AddJob. AddJob must fail on
6337          * non-local printers */
6338
6339         if (r->in.level != 1) {
6340                 return WERR_UNKNOWN_LEVEL;
6341         }
6342
6343         return WERR_INVALID_PARAM;
6344 }
6345
6346 /****************************************************************************
6347 fill_job_info1
6348 ****************************************************************************/
6349
6350 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6351                              struct spoolss_JobInfo1 *r,
6352                              const print_queue_struct *queue,
6353                              int position, int snum,
6354                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6355 {
6356         struct tm *t;
6357
6358         t = gmtime(&queue->time);
6359
6360         r->job_id               = queue->job;
6361
6362         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6363         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6364         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6365         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6366         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6367         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6368         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6369         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6370         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6371         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6372         r->text_status          = talloc_strdup(mem_ctx, "");
6373         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6374
6375         r->status               = nt_printj_status(queue->status);
6376         r->priority             = queue->priority;
6377         r->position             = position;
6378         r->total_pages          = queue->page_count;
6379         r->pages_printed        = 0; /* ??? */
6380
6381         init_systemtime(&r->submitted, t);
6382
6383         return WERR_OK;
6384 }
6385
6386 /****************************************************************************
6387 fill_job_info2
6388 ****************************************************************************/
6389
6390 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6391                              struct spoolss_JobInfo2 *r,
6392                              const print_queue_struct *queue,
6393                              int position, int snum,
6394                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6395                              struct spoolss_DeviceMode *devmode)
6396 {
6397         struct tm *t;
6398
6399         t = gmtime(&queue->time);
6400
6401         r->job_id               = queue->job;
6402
6403         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6404         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6405         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6406         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6407         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6408         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6409         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6410         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6411         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6412         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6413         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6414         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6415         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6416         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6417         r->parameters           = talloc_strdup(mem_ctx, "");
6418         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6419         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6420         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6421
6422         r->devmode              = devmode;
6423
6424         r->text_status          = talloc_strdup(mem_ctx, "");
6425         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6426
6427         r->secdesc              = NULL;
6428
6429         r->status               = nt_printj_status(queue->status);
6430         r->priority             = queue->priority;
6431         r->position             = position;
6432         r->start_time           = 0;
6433         r->until_time           = 0;
6434         r->total_pages          = queue->page_count;
6435         r->size                 = queue->size;
6436         init_systemtime(&r->submitted, t);
6437         r->time                 = 0;
6438         r->pages_printed        = 0; /* ??? */
6439
6440         return WERR_OK;
6441 }
6442
6443 /****************************************************************************
6444  Enumjobs at level 1.
6445 ****************************************************************************/
6446
6447 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6448                               const print_queue_struct *queue,
6449                               uint32_t num_queues, int snum,
6450                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6451                               union spoolss_JobInfo **info_p,
6452                               uint32_t *count)
6453 {
6454         union spoolss_JobInfo *info;
6455         int i;
6456         WERROR result = WERR_OK;
6457
6458         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6459         W_ERROR_HAVE_NO_MEMORY(info);
6460
6461         *count = num_queues;
6462
6463         for (i=0; i<*count; i++) {
6464                 result = fill_job_info1(info,
6465                                         &info[i].info1,
6466                                         &queue[i],
6467                                         i,
6468                                         snum,
6469                                         ntprinter);
6470                 if (!W_ERROR_IS_OK(result)) {
6471                         goto out;
6472                 }
6473         }
6474
6475  out:
6476         if (!W_ERROR_IS_OK(result)) {
6477                 TALLOC_FREE(info);
6478                 *count = 0;
6479                 return result;
6480         }
6481
6482         *info_p = info;
6483
6484         return WERR_OK;
6485 }
6486
6487 /****************************************************************************
6488  Enumjobs at level 2.
6489 ****************************************************************************/
6490
6491 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6492                               const print_queue_struct *queue,
6493                               uint32_t num_queues, int snum,
6494                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6495                               union spoolss_JobInfo **info_p,
6496                               uint32_t *count)
6497 {
6498         union spoolss_JobInfo *info;
6499         int i;
6500         WERROR result = WERR_OK;
6501
6502         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6503         W_ERROR_HAVE_NO_MEMORY(info);
6504
6505         *count = num_queues;
6506
6507         for (i=0; i<*count; i++) {
6508
6509                 struct spoolss_DeviceMode *devmode;
6510
6511                 devmode = construct_dev_mode_new(info, lp_const_servicename(snum));
6512                 if (!devmode) {
6513                         result = WERR_NOMEM;
6514                         goto out;
6515                 }
6516
6517                 result = fill_job_info2(info,
6518                                         &info[i].info2,
6519                                         &queue[i],
6520                                         i,
6521                                         snum,
6522                                         ntprinter,
6523                                         devmode);
6524                 if (!W_ERROR_IS_OK(result)) {
6525                         goto out;
6526                 }
6527         }
6528
6529  out:
6530         if (!W_ERROR_IS_OK(result)) {
6531                 TALLOC_FREE(info);
6532                 *count = 0;
6533                 return result;
6534         }
6535
6536         *info_p = info;
6537
6538         return WERR_OK;
6539 }
6540
6541 /****************************************************************
6542  _spoolss_EnumJobs
6543 ****************************************************************/
6544
6545 WERROR _spoolss_EnumJobs(pipes_struct *p,
6546                          struct spoolss_EnumJobs *r)
6547 {
6548         WERROR result;
6549         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6550         int snum;
6551         print_status_struct prt_status;
6552         print_queue_struct *queue = NULL;
6553         uint32_t count;
6554
6555         /* that's an [in out] buffer */
6556
6557         if (!r->in.buffer && (r->in.offered != 0)) {
6558                 return WERR_INVALID_PARAM;
6559         }
6560
6561         DEBUG(4,("_spoolss_EnumJobs\n"));
6562
6563         *r->out.needed = 0;
6564         *r->out.count = 0;
6565         *r->out.info = NULL;
6566
6567         /* lookup the printer snum and tdb entry */
6568
6569         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6570                 return WERR_BADFID;
6571         }
6572
6573         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6574         if (!W_ERROR_IS_OK(result)) {
6575                 return result;
6576         }
6577
6578         count = print_queue_status(snum, &queue, &prt_status);
6579         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6580                 count, prt_status.status, prt_status.message));
6581
6582         if (count == 0) {
6583                 SAFE_FREE(queue);
6584                 free_a_printer(&ntprinter, 2);
6585                 return WERR_OK;
6586         }
6587
6588         switch (r->in.level) {
6589         case 1:
6590                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6591                                          ntprinter, r->out.info, r->out.count);
6592                 break;
6593         case 2:
6594                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6595                                          ntprinter, r->out.info, r->out.count);
6596                 break;
6597         default:
6598                 result = WERR_UNKNOWN_LEVEL;
6599                 break;
6600         }
6601
6602         SAFE_FREE(queue);
6603         free_a_printer(&ntprinter, 2);
6604
6605         if (!W_ERROR_IS_OK(result)) {
6606                 return result;
6607         }
6608
6609         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6610                                                      spoolss_EnumJobs, NULL,
6611                                                      *r->out.info, r->in.level,
6612                                                      *r->out.count);
6613         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6614         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6615
6616         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6617 }
6618
6619 /****************************************************************
6620  _spoolss_ScheduleJob
6621 ****************************************************************/
6622
6623 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6624                             struct spoolss_ScheduleJob *r)
6625 {
6626         return WERR_OK;
6627 }
6628
6629 /****************************************************************
6630  _spoolss_SetJob
6631 ****************************************************************/
6632
6633 WERROR _spoolss_SetJob(pipes_struct *p,
6634                        struct spoolss_SetJob *r)
6635 {
6636         POLICY_HND *handle = r->in.handle;
6637         uint32 jobid = r->in.job_id;
6638         uint32 command = r->in.command;
6639
6640         int snum;
6641         WERROR errcode = WERR_BADFUNC;
6642
6643         if (!get_printer_snum(p, handle, &snum, NULL)) {
6644                 return WERR_BADFID;
6645         }
6646
6647         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6648                 return WERR_INVALID_PRINTER_NAME;
6649         }
6650
6651         switch (command) {
6652         case SPOOLSS_JOB_CONTROL_CANCEL:
6653         case SPOOLSS_JOB_CONTROL_DELETE:
6654                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6655                         errcode = WERR_OK;
6656                 }
6657                 break;
6658         case SPOOLSS_JOB_CONTROL_PAUSE:
6659                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6660                         errcode = WERR_OK;
6661                 }
6662                 break;
6663         case SPOOLSS_JOB_CONTROL_RESTART:
6664         case SPOOLSS_JOB_CONTROL_RESUME:
6665                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6666                         errcode = WERR_OK;
6667                 }
6668                 break;
6669         default:
6670                 return WERR_UNKNOWN_LEVEL;
6671         }
6672
6673         return errcode;
6674 }
6675
6676 /****************************************************************************
6677  Enumerates all printer drivers at level 1.
6678 ****************************************************************************/
6679
6680 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6681                                         const char *servername,
6682                                         const char *architecture,
6683                                         union spoolss_DriverInfo **info_p,
6684                                         uint32_t *count)
6685 {
6686         int i;
6687         int ndrivers;
6688         uint32_t version;
6689         fstring *list = NULL;
6690         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6691         union spoolss_DriverInfo *info = NULL;
6692         WERROR result = WERR_OK;
6693
6694         *count = 0;
6695
6696         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6697                 list = NULL;
6698                 ndrivers = get_ntdrivers(&list, architecture, version);
6699                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6700                         ndrivers, architecture, version));
6701
6702                 if (ndrivers == -1) {
6703                         result = WERR_NOMEM;
6704                         goto out;
6705                 }
6706
6707                 if (ndrivers != 0) {
6708                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6709                                                     union spoolss_DriverInfo,
6710                                                     *count + ndrivers);
6711                         if (!info) {
6712                                 DEBUG(0,("enumprinterdrivers_level1: "
6713                                         "failed to enlarge driver info buffer!\n"));
6714                                 result = WERR_NOMEM;
6715                                 goto out;
6716                         }
6717                 }
6718
6719                 for (i=0; i<ndrivers; i++) {
6720                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6721                         ZERO_STRUCT(driver);
6722                         result = get_a_printer_driver(&driver, 3, list[i],
6723                                                       architecture, version);
6724                         if (!W_ERROR_IS_OK(result)) {
6725                                 goto out;
6726                         }
6727                         result = fill_printer_driver_info1(info, &info[*count+i].info1,
6728                                                            &driver, servername,
6729                                                            architecture);
6730                         if (!W_ERROR_IS_OK(result)) {
6731                                 free_a_printer_driver(driver, 3);
6732                                 goto out;
6733                         }
6734                         free_a_printer_driver(driver, 3);
6735                 }
6736
6737                 *count += ndrivers;
6738                 SAFE_FREE(list);
6739         }
6740
6741  out:
6742         SAFE_FREE(list);
6743
6744         if (!W_ERROR_IS_OK(result)) {
6745                 TALLOC_FREE(info);
6746                 *count = 0;
6747                 return result;
6748         }
6749
6750         *info_p = info;
6751
6752         return WERR_OK;
6753 }
6754
6755 /****************************************************************************
6756  Enumerates all printer drivers at level 2.
6757 ****************************************************************************/
6758
6759 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6760                                         const char *servername,
6761                                         const char *architecture,
6762                                         union spoolss_DriverInfo **info_p,
6763                                         uint32_t *count)
6764 {
6765         int i;
6766         int ndrivers;
6767         uint32_t version;
6768         fstring *list = NULL;
6769         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6770         union spoolss_DriverInfo *info = NULL;
6771         WERROR result = WERR_OK;
6772
6773         *count = 0;
6774
6775         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6776                 list = NULL;
6777                 ndrivers = get_ntdrivers(&list, architecture, version);
6778                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6779                         ndrivers, architecture, version));
6780
6781                 if (ndrivers == -1) {
6782                         result = WERR_NOMEM;
6783                         goto out;
6784                 }
6785
6786                 if (ndrivers != 0) {
6787                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6788                                                     union spoolss_DriverInfo,
6789                                                     *count + ndrivers);
6790                         if (!info) {
6791                                 DEBUG(0,("enumprinterdrivers_level2: "
6792                                         "failed to enlarge driver info buffer!\n"));
6793                                 result = WERR_NOMEM;
6794                                 goto out;
6795                         }
6796                 }
6797
6798                 for (i=0; i<ndrivers; i++) {
6799                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6800                         ZERO_STRUCT(driver);
6801                         result = get_a_printer_driver(&driver, 3, list[i],
6802                                                       architecture, version);
6803                         if (!W_ERROR_IS_OK(result)) {
6804                                 goto out;
6805                         }
6806                         result = fill_printer_driver_info2(info, &info[*count+i].info2,
6807                                                            &driver, servername);
6808                         if (!W_ERROR_IS_OK(result)) {
6809                                 free_a_printer_driver(driver, 3);
6810                                 goto out;
6811                         }
6812                         free_a_printer_driver(driver, 3);
6813                 }
6814
6815                 *count += ndrivers;
6816                 SAFE_FREE(list);
6817         }
6818
6819  out:
6820         SAFE_FREE(list);
6821
6822         if (!W_ERROR_IS_OK(result)) {
6823                 TALLOC_FREE(info);
6824                 *count = 0;
6825                 return result;
6826         }
6827
6828         *info_p = info;
6829
6830         return WERR_OK;
6831 }
6832
6833 /****************************************************************************
6834  Enumerates all printer drivers at level 3.
6835 ****************************************************************************/
6836
6837 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6838                                         const char *servername,
6839                                         const char *architecture,
6840                                         union spoolss_DriverInfo **info_p,
6841                                         uint32_t *count)
6842 {
6843         int i;
6844         int ndrivers;
6845         uint32_t version;
6846         fstring *list = NULL;
6847         union spoolss_DriverInfo *info = NULL;
6848         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6849         WERROR result = WERR_OK;
6850
6851         *count = 0;
6852
6853         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6854                 list = NULL;
6855                 ndrivers = get_ntdrivers(&list, architecture, version);
6856                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6857                         ndrivers, architecture, version));
6858
6859                 if (ndrivers == -1) {
6860                         result = WERR_NOMEM;
6861                         goto out;
6862                 }
6863
6864                 if (ndrivers != 0) {
6865                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6866                                                     union spoolss_DriverInfo,
6867                                                     *count + ndrivers);
6868                         if (!info) {
6869                                 DEBUG(0,("enumprinterdrivers_level3: "
6870                                         "failed to enlarge driver info buffer!\n"));
6871                                 result = WERR_NOMEM;
6872                                 goto out;
6873                         }
6874                 }
6875
6876                 for (i=0; i<ndrivers; i++) {
6877                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6878                         ZERO_STRUCT(driver);
6879                         result = get_a_printer_driver(&driver, 3, list[i],
6880                                                       architecture, version);
6881                         if (!W_ERROR_IS_OK(result)) {
6882                                 goto out;
6883                         }
6884                         result = fill_printer_driver_info3(info, &info[*count+i].info3,
6885                                                            &driver, servername);
6886                         if (!W_ERROR_IS_OK(result)) {
6887                                 free_a_printer_driver(driver, 3);
6888                                 goto out;
6889                         }
6890
6891                         free_a_printer_driver(driver, 3);
6892                 }
6893
6894                 *count += ndrivers;
6895                 SAFE_FREE(list);
6896         }
6897
6898  out:
6899         SAFE_FREE(list);
6900
6901         if (!W_ERROR_IS_OK(result)) {
6902                 TALLOC_FREE(info);
6903                 *count = 0;
6904                 return result;
6905         }
6906
6907         *info_p = info;
6908
6909         return WERR_OK;
6910 }
6911
6912 /****************************************************************
6913  _spoolss_EnumPrinterDrivers
6914 ****************************************************************/
6915
6916 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6917                                    struct spoolss_EnumPrinterDrivers *r)
6918 {
6919         const char *cservername;
6920         WERROR result;
6921
6922         /* that's an [in out] buffer */
6923
6924         if (!r->in.buffer && (r->in.offered != 0)) {
6925                 return WERR_INVALID_PARAM;
6926         }
6927
6928         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6929
6930         *r->out.needed = 0;
6931         *r->out.count = 0;
6932         *r->out.info = NULL;
6933
6934         cservername = canon_servername(r->in.server);
6935
6936         if (!is_myname_or_ipaddr(cservername)) {
6937                 return WERR_UNKNOWN_PRINTER_DRIVER;
6938         }
6939
6940         switch (r->in.level) {
6941         case 1:
6942                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6943                                                    r->in.environment,
6944                                                    r->out.info, r->out.count);
6945                 break;
6946         case 2:
6947                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6948                                                    r->in.environment,
6949                                                    r->out.info, r->out.count);
6950                 break;
6951         case 3:
6952                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6953                                                    r->in.environment,
6954                                                    r->out.info, r->out.count);
6955                 break;
6956         default:
6957                 return WERR_UNKNOWN_LEVEL;
6958         }
6959
6960         if (!W_ERROR_IS_OK(result)) {
6961                 return result;
6962         }
6963
6964         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6965                                                      spoolss_EnumPrinterDrivers, NULL,
6966                                                      *r->out.info, r->in.level,
6967                                                      *r->out.count);
6968         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6969         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6970
6971         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6972 }
6973
6974 /****************************************************************************
6975 ****************************************************************************/
6976
6977 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6978                                struct spoolss_FormInfo1 *r,
6979                                const nt_forms_struct *form)
6980 {
6981         r->form_name    = talloc_strdup(mem_ctx, form->name);
6982         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6983
6984         r->flags        = form->flag;
6985         r->size.width   = form->width;
6986         r->size.height  = form->length;
6987         r->area.left    = form->left;
6988         r->area.top     = form->top;
6989         r->area.right   = form->right;
6990         r->area.bottom  = form->bottom;
6991
6992         return WERR_OK;
6993 }
6994
6995 /****************************************************************
6996  spoolss_enumforms_level1
6997 ****************************************************************/
6998
6999 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7000                                        const nt_forms_struct *builtin_forms,
7001                                        uint32_t num_builtin_forms,
7002                                        const nt_forms_struct *user_forms,
7003                                        uint32_t num_user_forms,
7004                                        union spoolss_FormInfo **info_p,
7005                                        uint32_t *count)
7006 {
7007         union spoolss_FormInfo *info;
7008         WERROR result = WERR_OK;
7009         int i;
7010
7011         *count = num_builtin_forms + num_user_forms;
7012
7013         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7014         W_ERROR_HAVE_NO_MEMORY(info);
7015
7016         /* construct the list of form structures */
7017         for (i=0; i<num_builtin_forms; i++) {
7018                 DEBUGADD(6,("Filling form number [%d]\n",i));
7019                 result = fill_form_info_1(info, &info[i].info1,
7020                                           &builtin_forms[i]);
7021                 if (!W_ERROR_IS_OK(result)) {
7022                         goto out;
7023                 }
7024         }
7025
7026         for (; i<num_user_forms; i++) {
7027                 DEBUGADD(6,("Filling form number [%d]\n",i));
7028                 result = fill_form_info_1(info, &info[i].info1,
7029                                           &user_forms[i-num_builtin_forms]);
7030                 if (!W_ERROR_IS_OK(result)) {
7031                         goto out;
7032                 }
7033         }
7034
7035  out:
7036         if (!W_ERROR_IS_OK(result)) {
7037                 TALLOC_FREE(info);
7038                 *count = 0;
7039                 return result;
7040         }
7041
7042         *info_p = info;
7043
7044         return WERR_OK;
7045 }
7046
7047 /****************************************************************
7048  _spoolss_EnumForms
7049 ****************************************************************/
7050
7051 WERROR _spoolss_EnumForms(pipes_struct *p,
7052                           struct spoolss_EnumForms *r)
7053 {
7054         WERROR result;
7055         nt_forms_struct *user_forms = NULL;
7056         nt_forms_struct *builtin_forms = NULL;
7057         uint32_t num_user_forms;
7058         uint32_t num_builtin_forms;
7059
7060         *r->out.count = 0;
7061         *r->out.needed = 0;
7062         *r->out.info = NULL;
7063
7064         /* that's an [in out] buffer */
7065
7066         if (!r->in.buffer && (r->in.offered != 0) ) {
7067                 return WERR_INVALID_PARAM;
7068         }
7069
7070         DEBUG(4,("_spoolss_EnumForms\n"));
7071         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7072         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7073
7074         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7075         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7076         num_user_forms = get_ntforms(&user_forms);
7077         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7078
7079         if (num_user_forms + num_builtin_forms == 0) {
7080                 SAFE_FREE(builtin_forms);
7081                 SAFE_FREE(user_forms);
7082                 return WERR_NO_MORE_ITEMS;
7083         }
7084
7085         switch (r->in.level) {
7086         case 1:
7087                 result = spoolss_enumforms_level1(p->mem_ctx,
7088                                                   builtin_forms,
7089                                                   num_builtin_forms,
7090                                                   user_forms,
7091                                                   num_user_forms,
7092                                                   r->out.info,
7093                                                   r->out.count);
7094                 break;
7095         default:
7096                 result = WERR_UNKNOWN_LEVEL;
7097                 break;
7098         }
7099
7100         SAFE_FREE(user_forms);
7101         SAFE_FREE(builtin_forms);
7102
7103         if (!W_ERROR_IS_OK(result)) {
7104                 return result;
7105         }
7106
7107         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7108                                                      spoolss_EnumForms, NULL,
7109                                                      *r->out.info, r->in.level,
7110                                                      *r->out.count);
7111         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7112         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7113
7114         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7115 }
7116
7117 /****************************************************************
7118 ****************************************************************/
7119
7120 static WERROR find_form_byname(const char *name,
7121                                nt_forms_struct *form)
7122 {
7123         nt_forms_struct *list = NULL;
7124         int num_forms = 0, i = 0;
7125
7126         if (get_a_builtin_ntform_by_string(name, form)) {
7127                 return WERR_OK;
7128         }
7129
7130         num_forms = get_ntforms(&list);
7131         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7132
7133         if (num_forms == 0) {
7134                 return WERR_BADFID;
7135         }
7136
7137         /* Check if the requested name is in the list of form structures */
7138         for (i = 0; i < num_forms; i++) {
7139
7140                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7141
7142                 if (strequal(name, list[i].name)) {
7143                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7144                         *form = list[i];
7145                         SAFE_FREE(list);
7146                         return WERR_OK;
7147                 }
7148         }
7149
7150         SAFE_FREE(list);
7151
7152         return WERR_BADFID;
7153 }
7154
7155 /****************************************************************
7156  _spoolss_GetForm
7157 ****************************************************************/
7158
7159 WERROR _spoolss_GetForm(pipes_struct *p,
7160                         struct spoolss_GetForm *r)
7161 {
7162         WERROR result;
7163         nt_forms_struct form;
7164
7165         /* that's an [in out] buffer */
7166
7167         if (!r->in.buffer && (r->in.offered != 0)) {
7168                 return WERR_INVALID_PARAM;
7169         }
7170
7171         DEBUG(4,("_spoolss_GetForm\n"));
7172         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7173         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7174
7175         result = find_form_byname(r->in.form_name, &form);
7176         if (!W_ERROR_IS_OK(result)) {
7177                 TALLOC_FREE(r->out.info);
7178                 return result;
7179         }
7180
7181         switch (r->in.level) {
7182         case 1:
7183                 result = fill_form_info_1(p->mem_ctx,
7184                                           &r->out.info->info1,
7185                                           &form);
7186                 break;
7187
7188         default:
7189                 result = WERR_UNKNOWN_LEVEL;
7190                 break;
7191         }
7192
7193         if (!W_ERROR_IS_OK(result)) {
7194                 TALLOC_FREE(r->out.info);
7195                 return result;
7196         }
7197
7198         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7199                                                r->out.info, r->in.level);
7200         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7201
7202         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7203 }
7204
7205 /****************************************************************************
7206 ****************************************************************************/
7207
7208 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7209                           struct spoolss_PortInfo1 *r,
7210                           const char *name)
7211 {
7212         r->port_name = talloc_strdup(mem_ctx, name);
7213         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7214
7215         return WERR_OK;
7216 }
7217
7218 /****************************************************************************
7219  TODO: This probably needs distinguish between TCP/IP and Local ports
7220  somehow.
7221 ****************************************************************************/
7222
7223 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7224                           struct spoolss_PortInfo2 *r,
7225                           const char *name)
7226 {
7227         r->port_name = talloc_strdup(mem_ctx, name);
7228         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7229
7230         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7231         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7232
7233         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7234         W_ERROR_HAVE_NO_MEMORY(r->description);
7235
7236         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7237         r->reserved = 0;
7238
7239         return WERR_OK;
7240 }
7241
7242
7243 /****************************************************************************
7244  wrapper around the enumer ports command
7245 ****************************************************************************/
7246
7247 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7248 {
7249         char *cmd = lp_enumports_cmd();
7250         char **qlines = NULL;
7251         char *command = NULL;
7252         int numlines;
7253         int ret;
7254         int fd;
7255
7256         *count = 0;
7257         *lines = NULL;
7258
7259         /* if no hook then just fill in the default port */
7260
7261         if ( !*cmd ) {
7262                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7263                         return WERR_NOMEM;
7264                 }
7265                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7266                         TALLOC_FREE(qlines);
7267                         return WERR_NOMEM;
7268                 }
7269                 qlines[1] = NULL;
7270                 numlines = 1;
7271         }
7272         else {
7273                 /* we have a valid enumport command */
7274
7275                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7276                 if (!command) {
7277                         return WERR_NOMEM;
7278                 }
7279
7280                 DEBUG(10,("Running [%s]\n", command));
7281                 ret = smbrun(command, &fd);
7282                 DEBUG(10,("Returned [%d]\n", ret));
7283                 TALLOC_FREE(command);
7284                 if (ret != 0) {
7285                         if (fd != -1) {
7286                                 close(fd);
7287                         }
7288                         return WERR_ACCESS_DENIED;
7289                 }
7290
7291                 numlines = 0;
7292                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7293                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7294                 close(fd);
7295         }
7296
7297         *count = numlines;
7298         *lines = qlines;
7299
7300         return WERR_OK;
7301 }
7302
7303 /****************************************************************************
7304  enumports level 1.
7305 ****************************************************************************/
7306
7307 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7308                                 union spoolss_PortInfo **info_p,
7309                                 uint32_t *count)
7310 {
7311         union spoolss_PortInfo *info = NULL;
7312         int i=0;
7313         WERROR result = WERR_OK;
7314         char **qlines = NULL;
7315         int numlines = 0;
7316
7317         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7318         if (!W_ERROR_IS_OK(result)) {
7319                 goto out;
7320         }
7321
7322         if (numlines) {
7323                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7324                 if (!info) {
7325                         DEBUG(10,("Returning WERR_NOMEM\n"));
7326                         result = WERR_NOMEM;
7327                         goto out;
7328                 }
7329
7330                 for (i=0; i<numlines; i++) {
7331                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7332                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7333                         if (!W_ERROR_IS_OK(result)) {
7334                                 goto out;
7335                         }
7336                 }
7337         }
7338         TALLOC_FREE(qlines);
7339
7340 out:
7341         if (!W_ERROR_IS_OK(result)) {
7342                 TALLOC_FREE(info);
7343                 TALLOC_FREE(qlines);
7344                 *count = 0;
7345                 *info_p = NULL;
7346                 return result;
7347         }
7348
7349         *info_p = info;
7350         *count = numlines;
7351
7352         return WERR_OK;
7353 }
7354
7355 /****************************************************************************
7356  enumports level 2.
7357 ****************************************************************************/
7358
7359 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7360                                 union spoolss_PortInfo **info_p,
7361                                 uint32_t *count)
7362 {
7363         union spoolss_PortInfo *info = NULL;
7364         int i=0;
7365         WERROR result = WERR_OK;
7366         char **qlines = NULL;
7367         int numlines = 0;
7368
7369         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7370         if (!W_ERROR_IS_OK(result)) {
7371                 goto out;
7372         }
7373
7374         if (numlines) {
7375                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7376                 if (!info) {
7377                         DEBUG(10,("Returning WERR_NOMEM\n"));
7378                         result = WERR_NOMEM;
7379                         goto out;
7380                 }
7381
7382                 for (i=0; i<numlines; i++) {
7383                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7384                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7385                         if (!W_ERROR_IS_OK(result)) {
7386                                 goto out;
7387                         }
7388                 }
7389         }
7390         TALLOC_FREE(qlines);
7391
7392 out:
7393         if (!W_ERROR_IS_OK(result)) {
7394                 TALLOC_FREE(info);
7395                 TALLOC_FREE(qlines);
7396                 *count = 0;
7397                 *info_p = NULL;
7398                 return result;
7399         }
7400
7401         *info_p = info;
7402         *count = numlines;
7403
7404         return WERR_OK;
7405 }
7406
7407 /****************************************************************
7408  _spoolss_EnumPorts
7409 ****************************************************************/
7410
7411 WERROR _spoolss_EnumPorts(pipes_struct *p,
7412                           struct spoolss_EnumPorts *r)
7413 {
7414         WERROR result;
7415
7416         /* that's an [in out] buffer */
7417
7418         if (!r->in.buffer && (r->in.offered != 0)) {
7419                 return WERR_INVALID_PARAM;
7420         }
7421
7422         DEBUG(4,("_spoolss_EnumPorts\n"));
7423
7424         *r->out.count = 0;
7425         *r->out.needed = 0;
7426         *r->out.info = NULL;
7427
7428         switch (r->in.level) {
7429         case 1:
7430                 result = enumports_level_1(p->mem_ctx, r->out.info,
7431                                            r->out.count);
7432                 break;
7433         case 2:
7434                 result = enumports_level_2(p->mem_ctx, r->out.info,
7435                                            r->out.count);
7436                 break;
7437         default:
7438                 return WERR_UNKNOWN_LEVEL;
7439         }
7440
7441         if (!W_ERROR_IS_OK(result)) {
7442                 return result;
7443         }
7444
7445         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7446                                                      spoolss_EnumPorts, NULL,
7447                                                      *r->out.info, r->in.level,
7448                                                      *r->out.count);
7449         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7450         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7451
7452         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7453 }
7454
7455 /****************************************************************************
7456 ****************************************************************************/
7457
7458 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7459                                            const char *server,
7460                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7461                                            struct spoolss_DeviceMode *devmode,
7462                                            struct security_descriptor *sec_desc,
7463                                            struct spoolss_UserLevelCtr *user_ctr,
7464                                            POLICY_HND *handle)
7465 {
7466         NT_PRINTER_INFO_LEVEL *printer = NULL;
7467         fstring name;
7468         int     snum;
7469         WERROR err = WERR_OK;
7470
7471         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7472                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7473                 return WERR_NOMEM;
7474         }
7475
7476         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7477         if (!convert_printer_info_new(info_ctr, printer)) {
7478                 free_a_printer(&printer, 2);
7479                 return WERR_NOMEM;
7480         }
7481
7482         /* check to see if the printer already exists */
7483
7484         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7485                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7486                         printer->info_2->sharename));
7487                 free_a_printer(&printer, 2);
7488                 return WERR_PRINTER_ALREADY_EXISTS;
7489         }
7490
7491         /* FIXME!!!  smbd should check to see if the driver is installed before
7492            trying to add a printer like this  --jerry */
7493
7494         if (*lp_addprinter_cmd() ) {
7495                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7496                                        printer) ) {
7497                         free_a_printer(&printer,2);
7498                         return WERR_ACCESS_DENIED;
7499                 }
7500         } else {
7501                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7502                         "smb.conf parameter \"addprinter command\" is defined. This"
7503                         "parameter must exist for this call to succeed\n",
7504                         printer->info_2->sharename ));
7505         }
7506
7507         /* use our primary netbios name since get_a_printer() will convert
7508            it to what the client expects on a case by case basis */
7509
7510         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7511              printer->info_2->sharename);
7512
7513
7514         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7515                 free_a_printer(&printer,2);
7516                 return WERR_ACCESS_DENIED;
7517         }
7518
7519         /* you must be a printer admin to add a new printer */
7520         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7521                 free_a_printer(&printer,2);
7522                 return WERR_ACCESS_DENIED;
7523         }
7524
7525         /*
7526          * Do sanity check on the requested changes for Samba.
7527          */
7528
7529         if (!check_printer_ok(printer->info_2, snum)) {
7530                 free_a_printer(&printer,2);
7531                 return WERR_INVALID_PARAM;
7532         }
7533
7534         /*
7535          * When a printer is created, the drivername bound to the printer is used
7536          * to lookup previously saved driver initialization info, which is then
7537          * bound to the new printer, simulating what happens in the Windows arch.
7538          */
7539
7540         if (!devmode)
7541         {
7542                 set_driver_init(printer, 2);
7543         }
7544         else
7545         {
7546                 /* A valid devmode was included, convert and link it
7547                 */
7548                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7549
7550                 if (!convert_devicemode_new(printer->info_2->printername,
7551                                             devmode,
7552                                             &printer->info_2->devmode))
7553                         return  WERR_NOMEM;
7554         }
7555
7556         /* write the ASCII on disk */
7557         err = mod_a_printer(printer, 2);
7558         if (!W_ERROR_IS_OK(err)) {
7559                 free_a_printer(&printer,2);
7560                 return err;
7561         }
7562
7563         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7564                 /* Handle open failed - remove addition. */
7565                 del_a_printer(printer->info_2->sharename);
7566                 free_a_printer(&printer,2);
7567                 ZERO_STRUCTP(handle);
7568                 return WERR_ACCESS_DENIED;
7569         }
7570
7571         update_c_setprinter(False);
7572         free_a_printer(&printer,2);
7573
7574         return WERR_OK;
7575 }
7576
7577 /****************************************************************
7578  _spoolss_AddPrinterEx
7579 ****************************************************************/
7580
7581 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7582                              struct spoolss_AddPrinterEx *r)
7583 {
7584         switch (r->in.info_ctr->level) {
7585         case 1:
7586                 /* we don't handle yet */
7587                 /* but I know what to do ... */
7588                 return WERR_UNKNOWN_LEVEL;
7589         case 2:
7590                 return spoolss_addprinterex_level_2(p, r->in.server,
7591                                                     r->in.info_ctr,
7592                                                     r->in.devmode_ctr->devmode,
7593                                                     r->in.secdesc_ctr->sd,
7594                                                     r->in.userlevel_ctr,
7595                                                     r->out.handle);
7596         default:
7597                 return WERR_UNKNOWN_LEVEL;
7598         }
7599 }
7600
7601 /****************************************************************
7602  _spoolss_AddPrinterDriver
7603 ****************************************************************/
7604
7605 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7606                                  struct spoolss_AddPrinterDriver *r)
7607 {
7608         uint32_t level = r->in.info_ctr->level;
7609         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7610         WERROR err = WERR_OK;
7611         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7612         fstring driver_name;
7613         uint32 version;
7614         const char *fn;
7615
7616         switch (p->hdr_req.opnum) {
7617                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7618                         fn = "_spoolss_AddPrinterDriver";
7619                         break;
7620                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7621                         fn = "_spoolss_AddPrinterDriverEx";
7622                         break;
7623                 default:
7624                         return WERR_INVALID_PARAM;
7625         }
7626
7627
7628         /* FIXME */
7629         if (level != 3 && level != 6) {
7630                 /* Clever hack from Martin Zielinski <mz@seh.de>
7631                  * to allow downgrade from level 8 (Vista).
7632                  */
7633                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7634                 return WERR_UNKNOWN_LEVEL;
7635         }
7636
7637         ZERO_STRUCT(driver);
7638
7639         if (!convert_printer_driver_info(info, &driver, level)) {
7640                 err = WERR_NOMEM;
7641                 goto done;
7642         }
7643
7644         DEBUG(5,("Cleaning driver's information\n"));
7645         err = clean_up_driver_struct(p, driver, level);
7646         if (!W_ERROR_IS_OK(err))
7647                 goto done;
7648
7649         DEBUG(5,("Moving driver to final destination\n"));
7650         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7651                                                               &err)) ) {
7652                 goto done;
7653         }
7654
7655         if (add_a_printer_driver(driver, level)!=0) {
7656                 err = WERR_ACCESS_DENIED;
7657                 goto done;
7658         }
7659
7660         switch(level) {
7661         case 3:
7662                 fstrcpy(driver_name,
7663                         driver.info_3->name ? driver.info_3->name : "");
7664                 break;
7665         case 6:
7666                 fstrcpy(driver_name,
7667                         driver.info_6->name ?  driver.info_6->name : "");
7668                 break;
7669         }
7670
7671         /*
7672          * I think this is where he DrvUpgradePrinter() hook would be
7673          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7674          * server.  Right now, we just need to send ourselves a message
7675          * to update each printer bound to this driver.   --jerry
7676          */
7677
7678         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7679                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7680                         fn, driver_name));
7681         }
7682
7683         /*
7684          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7685          * decide if the driver init data should be deleted. The rules are:
7686          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7687          *  2) delete init data only if there is no 2k/Xp driver
7688          *  3) always delete init data
7689          * The generalized rule is always use init data from the highest order driver.
7690          * It is necessary to follow the driver install by an initialization step to
7691          * finish off this process.
7692         */
7693         if (level == 3)
7694                 version = driver.info_3->cversion;
7695         else if (level == 6)
7696                 version = driver.info_6->version;
7697         else
7698                 version = -1;
7699         switch (version) {
7700                 /*
7701                  * 9x printer driver - never delete init data
7702                 */
7703                 case 0:
7704                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7705                                 fn, driver_name));
7706                         break;
7707
7708                 /*
7709                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7710                  * there is no 2k/Xp driver init data for this driver name.
7711                 */
7712                 case 2:
7713                 {
7714                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7715
7716                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7717                                 /*
7718                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7719                                 */
7720                                 if (!del_driver_init(driver_name))
7721                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7722                                                 fn, driver_name));
7723                         } else {
7724                                 /*
7725                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7726                                 */
7727                                 free_a_printer_driver(driver1,3);
7728                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7729                                         fn, driver_name));
7730                         }
7731                 }
7732                 break;
7733
7734                 /*
7735                  * 2k or Xp printer driver - always delete init data
7736                 */
7737                 case 3:
7738                         if (!del_driver_init(driver_name))
7739                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7740                                         fn, driver_name));
7741                         break;
7742
7743                 default:
7744                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7745                         break;
7746         }
7747
7748
7749 done:
7750         free_a_printer_driver(driver, level);
7751         return err;
7752 }
7753
7754 /****************************************************************
7755  _spoolss_AddPrinterDriverEx
7756 ****************************************************************/
7757
7758 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7759                                    struct spoolss_AddPrinterDriverEx *r)
7760 {
7761         struct spoolss_AddPrinterDriver a;
7762
7763         /*
7764          * we only support the semantics of AddPrinterDriver()
7765          * i.e. only copy files that are newer than existing ones
7766          */
7767
7768         if (r->in.flags != APD_COPY_NEW_FILES) {
7769                 return WERR_ACCESS_DENIED;
7770         }
7771
7772         a.in.servername         = r->in.servername;
7773         a.in.info_ctr           = r->in.info_ctr;
7774
7775         return _spoolss_AddPrinterDriver(p, &a);
7776 }
7777
7778 /****************************************************************************
7779 ****************************************************************************/
7780
7781 struct _spoolss_paths {
7782         int type;
7783         const char *share;
7784         const char *dir;
7785 };
7786
7787 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7788
7789 static const struct _spoolss_paths spoolss_paths[]= {
7790         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7791         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7792 };
7793
7794 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7795                                           const char *servername,
7796                                           const char *environment,
7797                                           int component,
7798                                           char **path)
7799 {
7800         const char *pservername = NULL;
7801         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7802         const char *short_archi;
7803
7804         *path = NULL;
7805
7806         /* environment may be empty */
7807         if (environment && strlen(environment)) {
7808                 long_archi = environment;
7809         }
7810
7811         /* servername may be empty */
7812         if (servername && strlen(servername)) {
7813                 pservername = canon_servername(servername);
7814
7815                 if (!is_myname_or_ipaddr(pservername)) {
7816                         return WERR_INVALID_PARAM;
7817                 }
7818         }
7819
7820         if (!(short_archi = get_short_archi(long_archi))) {
7821                 return WERR_INVALID_ENVIRONMENT;
7822         }
7823
7824         switch (component) {
7825         case SPOOLSS_PRTPROCS_PATH:
7826         case SPOOLSS_DRIVER_PATH:
7827                 if (pservername) {
7828                         *path = talloc_asprintf(mem_ctx,
7829                                         "\\\\%s\\%s\\%s",
7830                                         pservername,
7831                                         spoolss_paths[component].share,
7832                                         short_archi);
7833                 } else {
7834                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7835                                         SPOOLSS_DEFAULT_SERVER_PATH,
7836                                         spoolss_paths[component].dir,
7837                                         short_archi);
7838                 }
7839                 break;
7840         default:
7841                 return WERR_INVALID_PARAM;
7842         }
7843
7844         if (!*path) {
7845                 return WERR_NOMEM;
7846         }
7847
7848         return WERR_OK;
7849 }
7850
7851 /****************************************************************************
7852 ****************************************************************************/
7853
7854 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7855                                           const char *servername,
7856                                           const char *environment,
7857                                           struct spoolss_DriverDirectoryInfo1 *r)
7858 {
7859         WERROR werr;
7860         char *path = NULL;
7861
7862         werr = compose_spoolss_server_path(mem_ctx,
7863                                            servername,
7864                                            environment,
7865                                            SPOOLSS_DRIVER_PATH,
7866                                            &path);
7867         if (!W_ERROR_IS_OK(werr)) {
7868                 return werr;
7869         }
7870
7871         DEBUG(4,("printer driver directory: [%s]\n", path));
7872
7873         r->directory_name = path;
7874
7875         return WERR_OK;
7876 }
7877
7878 /****************************************************************
7879  _spoolss_GetPrinterDriverDirectory
7880 ****************************************************************/
7881
7882 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7883                                           struct spoolss_GetPrinterDriverDirectory *r)
7884 {
7885         WERROR werror;
7886
7887         /* that's an [in out] buffer */
7888
7889         if (!r->in.buffer && (r->in.offered != 0)) {
7890                 return WERR_INVALID_PARAM;
7891         }
7892
7893         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7894                 r->in.level));
7895
7896         *r->out.needed = 0;
7897
7898         /* r->in.level is ignored */
7899
7900         werror = getprinterdriverdir_level_1(p->mem_ctx,
7901                                              r->in.server,
7902                                              r->in.environment,
7903                                              &r->out.info->info1);
7904         if (!W_ERROR_IS_OK(werror)) {
7905                 TALLOC_FREE(r->out.info);
7906                 return werror;
7907         }
7908
7909         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7910                                                r->out.info, r->in.level);
7911         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7912
7913         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7914 }
7915
7916 /****************************************************************************
7917 ****************************************************************************/
7918
7919 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7920 {
7921         POLICY_HND *handle = &q_u->handle;
7922         uint32 idx               = q_u->index;
7923         uint32 in_value_len      = q_u->valuesize;
7924         uint32 in_data_len       = q_u->datasize;
7925         uint32 *out_max_value_len = &r_u->valuesize;
7926         uint16 **out_value       = &r_u->value;
7927         uint32 *out_value_len    = &r_u->realvaluesize;
7928         uint32 *out_type         = &r_u->type;
7929         uint32 *out_max_data_len = &r_u->datasize;
7930         uint8  **data_out        = &r_u->data;
7931         uint32 *out_data_len     = &r_u->realdatasize;
7932
7933         NT_PRINTER_INFO_LEVEL *printer = NULL;
7934
7935         uint32          biggest_valuesize;
7936         uint32          biggest_datasize;
7937         uint32          data_len;
7938         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7939         int             snum;
7940         WERROR          result;
7941         REGISTRY_VALUE  *val = NULL;
7942         NT_PRINTER_DATA *p_data;
7943         int             i, key_index, num_values;
7944         int             name_length;
7945
7946         *out_type = 0;
7947
7948         *out_max_data_len = 0;
7949         *data_out         = NULL;
7950         *out_data_len     = 0;
7951
7952         DEBUG(5,("spoolss_enumprinterdata\n"));
7953
7954         if (!Printer) {
7955                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7956                 return WERR_BADFID;
7957         }
7958
7959         if (!get_printer_snum(p,handle, &snum, NULL))
7960                 return WERR_BADFID;
7961
7962         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7963         if (!W_ERROR_IS_OK(result))
7964                 return result;
7965
7966         p_data = printer->info_2->data;
7967         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7968
7969         result = WERR_OK;
7970
7971         /*
7972          * The NT machine wants to know the biggest size of value and data
7973          *
7974          * cf: MSDN EnumPrinterData remark section
7975          */
7976
7977         if ( !in_value_len && !in_data_len && (key_index != -1) )
7978         {
7979                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7980
7981                 biggest_valuesize = 0;
7982                 biggest_datasize  = 0;
7983
7984                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7985
7986                 for ( i=0; i<num_values; i++ )
7987                 {
7988                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7989
7990                         name_length = strlen(val->valuename);
7991                         if ( strlen(val->valuename) > biggest_valuesize )
7992                                 biggest_valuesize = name_length;
7993
7994                         if ( val->size > biggest_datasize )
7995                                 biggest_datasize = val->size;
7996
7997                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7998                                 biggest_datasize));
7999                 }
8000
8001                 /* the value is an UNICODE string but real_value_size is the length
8002                    in bytes including the trailing 0 */
8003
8004                 *out_value_len = 2 * (1+biggest_valuesize);
8005                 *out_data_len  = biggest_datasize;
8006
8007                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8008
8009                 goto done;
8010         }
8011
8012         /*
8013          * the value len is wrong in NT sp3
8014          * that's the number of bytes not the number of unicode chars
8015          */
8016
8017         if ( key_index != -1 )
8018                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8019
8020         if ( !val )
8021         {
8022
8023                 /* out_value should default to "" or else NT4 has
8024                    problems unmarshalling the response */
8025
8026                 *out_max_value_len=(in_value_len/sizeof(uint16));
8027
8028                 if (in_value_len) {
8029                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8030                         {
8031                                 result = WERR_NOMEM;
8032                                 goto done;
8033                         }
8034                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8035                 } else {
8036                         *out_value=NULL;
8037                         *out_value_len = 0;
8038                 }
8039
8040                 /* the data is counted in bytes */
8041
8042                 *out_max_data_len = in_data_len;
8043                 *out_data_len     = in_data_len;
8044
8045                 /* only allocate when given a non-zero data_len */
8046
8047                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8048                 {
8049                         result = WERR_NOMEM;
8050                         goto done;
8051                 }
8052
8053                 result = WERR_NO_MORE_ITEMS;
8054         }
8055         else
8056         {
8057                 /*
8058                  * the value is:
8059                  * - counted in bytes in the request
8060                  * - counted in UNICODE chars in the max reply
8061                  * - counted in bytes in the real size
8062                  *
8063                  * take a pause *before* coding not *during* coding
8064                  */
8065
8066                 /* name */
8067                 *out_max_value_len=(in_value_len/sizeof(uint16));
8068                 if (in_value_len) {
8069                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8070                         {
8071                                 result = WERR_NOMEM;
8072                                 goto done;
8073                         }
8074
8075                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8076                 } else {
8077                         *out_value = NULL;
8078                         *out_value_len = 0;
8079                 }
8080
8081                 /* type */
8082
8083                 *out_type = regval_type( val );
8084
8085                 /* data - counted in bytes */
8086
8087                 *out_max_data_len = in_data_len;
8088                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8089                 {
8090                         result = WERR_NOMEM;
8091                         goto done;
8092                 }
8093                 data_len = regval_size(val);
8094                 if ( *data_out && data_len )
8095                         memcpy( *data_out, regval_data_p(val), data_len );
8096                 *out_data_len = data_len;
8097         }
8098
8099 done:
8100         free_a_printer(&printer, 2);
8101         return result;
8102 }
8103
8104 /****************************************************************************
8105 ****************************************************************************/
8106
8107 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8108 {
8109         POLICY_HND              *handle = &q_u->handle;
8110         UNISTR2                 *value = &q_u->value;
8111         uint32                  type = q_u->type;
8112         uint8                   *data = q_u->data;
8113         uint32                  real_len = q_u->real_len;
8114
8115         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8116         int                     snum=0;
8117         WERROR                  status = WERR_OK;
8118         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8119         fstring                 valuename;
8120
8121         DEBUG(5,("spoolss_setprinterdata\n"));
8122
8123         if (!Printer) {
8124                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8125                 return WERR_BADFID;
8126         }
8127
8128         if ( Printer->printer_type == SPLHND_SERVER ) {
8129                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8130                 return WERR_INVALID_PARAM;
8131         }
8132
8133         if (!get_printer_snum(p,handle, &snum, NULL))
8134                 return WERR_BADFID;
8135
8136         /*
8137          * Access check : NT returns "access denied" if you make a
8138          * SetPrinterData call without the necessary privildge.
8139          * we were originally returning OK if nothing changed
8140          * which made Win2k issue **a lot** of SetPrinterData
8141          * when connecting to a printer  --jerry
8142          */
8143
8144         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8145         {
8146                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8147                 status = WERR_ACCESS_DENIED;
8148                 goto done;
8149         }
8150
8151         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8152         if (!W_ERROR_IS_OK(status))
8153                 return status;
8154
8155         unistr2_to_ascii(valuename, value, sizeof(valuename));
8156
8157         /*
8158          * When client side code sets a magic printer data key, detect it and save
8159          * the current printer data and the magic key's data (its the DEVMODE) for
8160          * future printer/driver initializations.
8161          */
8162         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8163         {
8164                 /* Set devmode and printer initialization info */
8165                 status = save_driver_init( printer, 2, data, real_len );
8166
8167                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8168         }
8169         else
8170         {
8171         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8172                                         type, data, real_len );
8173                 if ( W_ERROR_IS_OK(status) )
8174                         status = mod_a_printer(printer, 2);
8175         }
8176
8177 done:
8178         free_a_printer(&printer, 2);
8179
8180         return status;
8181 }
8182
8183 /****************************************************************
8184  _spoolss_ResetPrinter
8185 ****************************************************************/
8186
8187 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8188                              struct spoolss_ResetPrinter *r)
8189 {
8190         POLICY_HND      *handle = r->in.handle;
8191         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8192         int             snum;
8193
8194         DEBUG(5,("_spoolss_ResetPrinter\n"));
8195
8196         /*
8197          * All we do is to check to see if the handle and queue is valid.
8198          * This call really doesn't mean anything to us because we only
8199          * support RAW printing.   --jerry
8200          */
8201
8202         if (!Printer) {
8203                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8204                         OUR_HANDLE(handle)));
8205                 return WERR_BADFID;
8206         }
8207
8208         if (!get_printer_snum(p,handle, &snum, NULL))
8209                 return WERR_BADFID;
8210
8211
8212         /* blindly return success */
8213         return WERR_OK;
8214 }
8215
8216 /****************************************************************
8217  _spoolss_DeletePrinterData
8218 ****************************************************************/
8219
8220 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8221                                   struct spoolss_DeletePrinterData *r)
8222 {
8223         POLICY_HND      *handle = r->in.handle;
8224         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8225         int             snum=0;
8226         WERROR          status = WERR_OK;
8227         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8228
8229         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8230
8231         if (!Printer) {
8232                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8233                         OUR_HANDLE(handle)));
8234                 return WERR_BADFID;
8235         }
8236
8237         if (!get_printer_snum(p, handle, &snum, NULL))
8238                 return WERR_BADFID;
8239
8240         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8241                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8242                         "printer properties change denied by handle\n"));
8243                 return WERR_ACCESS_DENIED;
8244         }
8245
8246         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8247         if (!W_ERROR_IS_OK(status))
8248                 return status;
8249
8250         if (!r->in.value_name) {
8251                 free_a_printer(&printer, 2);
8252                 return WERR_NOMEM;
8253         }
8254
8255         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8256                                         r->in.value_name );
8257
8258         if ( W_ERROR_IS_OK(status) )
8259                 mod_a_printer( printer, 2 );
8260
8261         free_a_printer(&printer, 2);
8262
8263         return status;
8264 }
8265
8266 /****************************************************************
8267  _spoolss_AddForm
8268 ****************************************************************/
8269
8270 WERROR _spoolss_AddForm(pipes_struct *p,
8271                         struct spoolss_AddForm *r)
8272 {
8273         POLICY_HND *handle = r->in.handle;
8274         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8275         nt_forms_struct tmpForm;
8276         int snum;
8277         WERROR status = WERR_OK;
8278         NT_PRINTER_INFO_LEVEL *printer = NULL;
8279
8280         int count=0;
8281         nt_forms_struct *list=NULL;
8282         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8283
8284         DEBUG(5,("_spoolss_AddForm\n"));
8285
8286         if (!Printer) {
8287                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8288                         OUR_HANDLE(handle)));
8289                 return WERR_BADFID;
8290         }
8291
8292
8293         /* forms can be added on printer of on the print server handle */
8294
8295         if ( Printer->printer_type == SPLHND_PRINTER )
8296         {
8297                 if (!get_printer_snum(p,handle, &snum, NULL))
8298                         return WERR_BADFID;
8299
8300                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8301                 if (!W_ERROR_IS_OK(status))
8302                         goto done;
8303         }
8304
8305         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8306                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8307                 status = WERR_ACCESS_DENIED;
8308                 goto done;
8309         }
8310
8311         /* can't add if builtin */
8312
8313         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8314                 status = WERR_FILE_EXISTS;
8315                 goto done;
8316         }
8317
8318         count = get_ntforms(&list);
8319
8320         if(!add_a_form(&list, form, &count)) {
8321                 status =  WERR_NOMEM;
8322                 goto done;
8323         }
8324
8325         write_ntforms(&list, count);
8326
8327         /*
8328          * ChangeID must always be set if this is a printer
8329          */
8330
8331         if ( Printer->printer_type == SPLHND_PRINTER )
8332                 status = mod_a_printer(printer, 2);
8333
8334 done:
8335         if ( printer )
8336                 free_a_printer(&printer, 2);
8337         SAFE_FREE(list);
8338
8339         return status;
8340 }
8341
8342 /****************************************************************
8343  _spoolss_DeleteForm
8344 ****************************************************************/
8345
8346 WERROR _spoolss_DeleteForm(pipes_struct *p,
8347                            struct spoolss_DeleteForm *r)
8348 {
8349         POLICY_HND *handle = r->in.handle;
8350         const char *form_name = r->in.form_name;
8351         nt_forms_struct tmpForm;
8352         int count=0;
8353         nt_forms_struct *list=NULL;
8354         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8355         int snum;
8356         WERROR status = WERR_OK;
8357         NT_PRINTER_INFO_LEVEL *printer = NULL;
8358
8359         DEBUG(5,("_spoolss_DeleteForm\n"));
8360
8361         if (!Printer) {
8362                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8363                         OUR_HANDLE(handle)));
8364                 return WERR_BADFID;
8365         }
8366
8367         /* forms can be deleted on printer of on the print server handle */
8368
8369         if ( Printer->printer_type == SPLHND_PRINTER )
8370         {
8371                 if (!get_printer_snum(p,handle, &snum, NULL))
8372                         return WERR_BADFID;
8373
8374                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8375                 if (!W_ERROR_IS_OK(status))
8376                         goto done;
8377         }
8378
8379         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8380                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8381                 status = WERR_ACCESS_DENIED;
8382                 goto done;
8383         }
8384
8385         /* can't delete if builtin */
8386
8387         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8388                 status = WERR_INVALID_PARAM;
8389                 goto done;
8390         }
8391
8392         count = get_ntforms(&list);
8393
8394         if ( !delete_a_form(&list, form_name, &count, &status ))
8395                 goto done;
8396
8397         /*
8398          * ChangeID must always be set if this is a printer
8399          */
8400
8401         if ( Printer->printer_type == SPLHND_PRINTER )
8402                 status = mod_a_printer(printer, 2);
8403
8404 done:
8405         if ( printer )
8406                 free_a_printer(&printer, 2);
8407         SAFE_FREE(list);
8408
8409         return status;
8410 }
8411
8412 /****************************************************************
8413  _spoolss_SetForm
8414 ****************************************************************/
8415
8416 WERROR _spoolss_SetForm(pipes_struct *p,
8417                         struct spoolss_SetForm *r)
8418 {
8419         POLICY_HND *handle = r->in.handle;
8420         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8421         nt_forms_struct tmpForm;
8422         int snum;
8423         WERROR status = WERR_OK;
8424         NT_PRINTER_INFO_LEVEL *printer = NULL;
8425
8426         int count=0;
8427         nt_forms_struct *list=NULL;
8428         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8429
8430         DEBUG(5,("_spoolss_SetForm\n"));
8431
8432         if (!Printer) {
8433                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8434                         OUR_HANDLE(handle)));
8435                 return WERR_BADFID;
8436         }
8437
8438         /* forms can be modified on printer of on the print server handle */
8439
8440         if ( Printer->printer_type == SPLHND_PRINTER )
8441         {
8442                 if (!get_printer_snum(p,handle, &snum, NULL))
8443                         return WERR_BADFID;
8444
8445                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8446                 if (!W_ERROR_IS_OK(status))
8447                         goto done;
8448         }
8449
8450         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8451                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8452                 status = WERR_ACCESS_DENIED;
8453                 goto done;
8454         }
8455
8456         /* can't set if builtin */
8457         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8458                 status = WERR_INVALID_PARAM;
8459                 goto done;
8460         }
8461
8462         count = get_ntforms(&list);
8463         update_a_form(&list, form, count);
8464         write_ntforms(&list, count);
8465
8466         /*
8467          * ChangeID must always be set if this is a printer
8468          */
8469
8470         if ( Printer->printer_type == SPLHND_PRINTER )
8471                 status = mod_a_printer(printer, 2);
8472
8473
8474 done:
8475         if ( printer )
8476                 free_a_printer(&printer, 2);
8477         SAFE_FREE(list);
8478
8479         return status;
8480 }
8481
8482 /****************************************************************************
8483  fill_print_processor1
8484 ****************************************************************************/
8485
8486 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8487                                     struct spoolss_PrintProcessorInfo1 *r,
8488                                     const char *print_processor_name)
8489 {
8490         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8491         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8492
8493         return WERR_OK;
8494 }
8495
8496 /****************************************************************************
8497  enumprintprocessors level 1.
8498 ****************************************************************************/
8499
8500 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8501                                           union spoolss_PrintProcessorInfo **info_p,
8502                                           uint32_t *count)
8503 {
8504         union spoolss_PrintProcessorInfo *info;
8505         WERROR result;
8506
8507         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8508         W_ERROR_HAVE_NO_MEMORY(info);
8509
8510         *count = 1;
8511
8512         result = fill_print_processor1(info, &info[0].info1, "winprint");
8513         if (!W_ERROR_IS_OK(result)) {
8514                 goto out;
8515         }
8516
8517  out:
8518         if (!W_ERROR_IS_OK(result)) {
8519                 TALLOC_FREE(info);
8520                 *count = 0;
8521                 return result;
8522         }
8523
8524         *info_p = info;
8525
8526         return WERR_OK;
8527 }
8528
8529 /****************************************************************
8530  _spoolss_EnumPrintProcessors
8531 ****************************************************************/
8532
8533 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8534                                     struct spoolss_EnumPrintProcessors *r)
8535 {
8536         WERROR result;
8537
8538         /* that's an [in out] buffer */
8539
8540         if (!r->in.buffer && (r->in.offered != 0)) {
8541                 return WERR_INVALID_PARAM;
8542         }
8543
8544         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8545
8546         /*
8547          * Enumerate the print processors ...
8548          *
8549          * Just reply with "winprint", to keep NT happy
8550          * and I can use my nice printer checker.
8551          */
8552
8553         *r->out.count = 0;
8554         *r->out.needed = 0;
8555         *r->out.info = NULL;
8556
8557         switch (r->in.level) {
8558         case 1:
8559                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8560                                                      r->out.count);
8561                 break;
8562         default:
8563                 return WERR_UNKNOWN_LEVEL;
8564         }
8565
8566         if (!W_ERROR_IS_OK(result)) {
8567                 return result;
8568         }
8569
8570         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8571                                                      spoolss_EnumPrintProcessors, NULL,
8572                                                      *r->out.info, r->in.level,
8573                                                      *r->out.count);
8574         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8575         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8576
8577         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8578 }
8579
8580 /****************************************************************************
8581  fill_printprocdatatype1
8582 ****************************************************************************/
8583
8584 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8585                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8586                                       const char *name_array)
8587 {
8588         r->name_array = talloc_strdup(mem_ctx, name_array);
8589         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8590
8591         return WERR_OK;
8592 }
8593
8594 /****************************************************************************
8595  enumprintprocdatatypes level 1.
8596 ****************************************************************************/
8597
8598 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8599                                              union spoolss_PrintProcDataTypesInfo **info_p,
8600                                              uint32_t *count)
8601 {
8602         WERROR result;
8603         union spoolss_PrintProcDataTypesInfo *info;
8604
8605         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8606         W_ERROR_HAVE_NO_MEMORY(info);
8607
8608         *count = 1;
8609
8610         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8611         if (!W_ERROR_IS_OK(result)) {
8612                 goto out;
8613         }
8614
8615  out:
8616         if (!W_ERROR_IS_OK(result)) {
8617                 TALLOC_FREE(info);
8618                 *count = 0;
8619                 return result;
8620         }
8621
8622         *info_p = info;
8623
8624         return WERR_OK;
8625 }
8626
8627 /****************************************************************
8628  _spoolss_EnumPrintProcDataTypes
8629 ****************************************************************/
8630
8631 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8632                                        struct spoolss_EnumPrintProcDataTypes *r)
8633 {
8634         WERROR result;
8635
8636         /* that's an [in out] buffer */
8637
8638         if (!r->in.buffer && (r->in.offered != 0)) {
8639                 return WERR_INVALID_PARAM;
8640         }
8641
8642         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8643
8644         *r->out.count = 0;
8645         *r->out.needed = 0;
8646         *r->out.info = NULL;
8647
8648         switch (r->in.level) {
8649         case 1:
8650                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8651                                                         r->out.count);
8652                 break;
8653         default:
8654                 return WERR_UNKNOWN_LEVEL;
8655         }
8656
8657         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8658                                                      spoolss_EnumPrintProcDataTypes, NULL,
8659                                                      *r->out.info, r->in.level,
8660                                                      *r->out.count);
8661         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8662         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8663
8664         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8665 }
8666
8667 /****************************************************************************
8668  fill_monitor_1
8669 ****************************************************************************/
8670
8671 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8672                              struct spoolss_MonitorInfo1 *r,
8673                              const char *monitor_name)
8674 {
8675         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8676         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8677
8678         return WERR_OK;
8679 }
8680
8681 /****************************************************************************
8682  fill_monitor_2
8683 ****************************************************************************/
8684
8685 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8686                              struct spoolss_MonitorInfo2 *r,
8687                              const char *monitor_name,
8688                              const char *environment,
8689                              const char *dll_name)
8690 {
8691         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8692         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8693         r->environment                  = talloc_strdup(mem_ctx, environment);
8694         W_ERROR_HAVE_NO_MEMORY(r->environment);
8695         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8696         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8697
8698         return WERR_OK;
8699 }
8700
8701 /****************************************************************************
8702  enumprintmonitors level 1.
8703 ****************************************************************************/
8704
8705 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8706                                         union spoolss_MonitorInfo **info_p,
8707                                         uint32_t *count)
8708 {
8709         union spoolss_MonitorInfo *info;
8710         WERROR result = WERR_OK;
8711
8712         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8713         W_ERROR_HAVE_NO_MEMORY(info);
8714
8715         *count = 2;
8716
8717         result = fill_monitor_1(info, &info[0].info1,
8718                                 SPL_LOCAL_PORT /* FIXME */);
8719         if (!W_ERROR_IS_OK(result)) {
8720                 goto out;
8721         }
8722
8723         result = fill_monitor_1(info, &info[1].info1,
8724                                 SPL_TCPIP_PORT /* FIXME */);
8725         if (!W_ERROR_IS_OK(result)) {
8726                 goto out;
8727         }
8728
8729 out:
8730         if (!W_ERROR_IS_OK(result)) {
8731                 TALLOC_FREE(info);
8732                 *count = 0;
8733                 return result;
8734         }
8735
8736         *info_p = info;
8737
8738         return WERR_OK;
8739 }
8740
8741 /****************************************************************************
8742  enumprintmonitors level 2.
8743 ****************************************************************************/
8744
8745 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8746                                         union spoolss_MonitorInfo **info_p,
8747                                         uint32_t *count)
8748 {
8749         union spoolss_MonitorInfo *info;
8750         WERROR result = WERR_OK;
8751
8752         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8753         W_ERROR_HAVE_NO_MEMORY(info);
8754
8755         *count = 2;
8756
8757         result = fill_monitor_2(info, &info[0].info2,
8758                                 SPL_LOCAL_PORT, /* FIXME */
8759                                 "Windows NT X86", /* FIXME */
8760                                 "localmon.dll");
8761         if (!W_ERROR_IS_OK(result)) {
8762                 goto out;
8763         }
8764
8765         result = fill_monitor_2(info, &info[1].info2,
8766                                 SPL_TCPIP_PORT, /* FIXME */
8767                                 "Windows NT X86", /* FIXME */
8768                                 "tcpmon.dll");
8769         if (!W_ERROR_IS_OK(result)) {
8770                 goto out;
8771         }
8772
8773 out:
8774         if (!W_ERROR_IS_OK(result)) {
8775                 TALLOC_FREE(info);
8776                 *count = 0;
8777                 return result;
8778         }
8779
8780         *info_p = info;
8781
8782         return WERR_OK;
8783 }
8784
8785 /****************************************************************
8786  _spoolss_EnumMonitors
8787 ****************************************************************/
8788
8789 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8790                              struct spoolss_EnumMonitors *r)
8791 {
8792         WERROR result;
8793
8794         /* that's an [in out] buffer */
8795
8796         if (!r->in.buffer && (r->in.offered != 0)) {
8797                 return WERR_INVALID_PARAM;
8798         }
8799
8800         DEBUG(5,("_spoolss_EnumMonitors\n"));
8801
8802         /*
8803          * Enumerate the print monitors ...
8804          *
8805          * Just reply with "Local Port", to keep NT happy
8806          * and I can use my nice printer checker.
8807          */
8808
8809         *r->out.count = 0;
8810         *r->out.needed = 0;
8811         *r->out.info = NULL;
8812
8813         switch (r->in.level) {
8814         case 1:
8815                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8816                                                    r->out.count);
8817                 break;
8818         case 2:
8819                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8820                                                    r->out.count);
8821                 break;
8822         default:
8823                 return WERR_UNKNOWN_LEVEL;
8824         }
8825
8826         if (!W_ERROR_IS_OK(result)) {
8827                 return result;
8828         }
8829
8830         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8831                                                      spoolss_EnumMonitors, NULL,
8832                                                      *r->out.info, r->in.level,
8833                                                      *r->out.count);
8834         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8835         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8836
8837         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8838 }
8839
8840 /****************************************************************************
8841 ****************************************************************************/
8842
8843 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8844                              const print_queue_struct *queue,
8845                              int count, int snum,
8846                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8847                              uint32_t jobid,
8848                              struct spoolss_JobInfo1 *r)
8849 {
8850         int i = 0;
8851         bool found = false;
8852
8853         for (i=0; i<count && found == false; i++) {
8854                 if (queue[i].job == (int)jobid) {
8855                         found = true;
8856                 }
8857         }
8858
8859         if (found == false) {
8860                 /* NT treats not found as bad param... yet another bad choice */
8861                 return WERR_INVALID_PARAM;
8862         }
8863
8864         return fill_job_info1(mem_ctx,
8865                               r,
8866                               &queue[i-1],
8867                               i,
8868                               snum,
8869                               ntprinter);
8870 }
8871
8872 /****************************************************************************
8873 ****************************************************************************/
8874
8875 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8876                              const print_queue_struct *queue,
8877                              int count, int snum,
8878                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8879                              uint32_t jobid,
8880                              struct spoolss_JobInfo2 *r)
8881 {
8882         int i = 0;
8883         bool found = false;
8884         struct spoolss_DeviceMode *devmode;
8885         NT_DEVICEMODE *nt_devmode;
8886         WERROR result;
8887
8888         for (i=0; i<count && found == false; i++) {
8889                 if (queue[i].job == (int)jobid) {
8890                         found = true;
8891                 }
8892         }
8893
8894         if (found == false) {
8895                 /* NT treats not found as bad param... yet another bad
8896                    choice */
8897                 return WERR_INVALID_PARAM;
8898         }
8899
8900         /*
8901          * if the print job does not have a DEVMODE associated with it,
8902          * just use the one for the printer. A NULL devicemode is not
8903          *  a failure condition
8904          */
8905
8906         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8907         if (nt_devmode) {
8908                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8909                 W_ERROR_HAVE_NO_MEMORY(devmode);
8910                 result = convert_nt_devicemode_new(devmode, devmode, nt_devmode);
8911                 if (!W_ERROR_IS_OK(result)) {
8912                         return result;
8913                 }
8914         } else {
8915                 devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
8916                 W_ERROR_HAVE_NO_MEMORY(devmode);
8917         }
8918
8919         return fill_job_info2(mem_ctx,
8920                               r,
8921                               &queue[i-1],
8922                               i,
8923                               snum,
8924                               ntprinter,
8925                               devmode);
8926 }
8927
8928 /****************************************************************
8929  _spoolss_GetJob
8930 ****************************************************************/
8931
8932 WERROR _spoolss_GetJob(pipes_struct *p,
8933                        struct spoolss_GetJob *r)
8934 {
8935         WERROR result = WERR_OK;
8936         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8937         int snum;
8938         int count;
8939         print_queue_struct      *queue = NULL;
8940         print_status_struct prt_status;
8941
8942         /* that's an [in out] buffer */
8943
8944         if (!r->in.buffer && (r->in.offered != 0)) {
8945                 return WERR_INVALID_PARAM;
8946         }
8947
8948         DEBUG(5,("_spoolss_GetJob\n"));
8949
8950         *r->out.needed = 0;
8951
8952         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8953                 return WERR_BADFID;
8954         }
8955
8956         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8957         if (!W_ERROR_IS_OK(result)) {
8958                 return result;
8959         }
8960
8961         count = print_queue_status(snum, &queue, &prt_status);
8962
8963         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8964                      count, prt_status.status, prt_status.message));
8965
8966         switch (r->in.level) {
8967         case 1:
8968                 result = getjob_level_1(p->mem_ctx,
8969                                         queue, count, snum, ntprinter,
8970                                         r->in.job_id, &r->out.info->info1);
8971                 break;
8972         case 2:
8973                 result = getjob_level_2(p->mem_ctx,
8974                                         queue, count, snum, ntprinter,
8975                                         r->in.job_id, &r->out.info->info2);
8976                 break;
8977         default:
8978                 result = WERR_UNKNOWN_LEVEL;
8979                 break;
8980         }
8981
8982         SAFE_FREE(queue);
8983         free_a_printer(&ntprinter, 2);
8984
8985         if (!W_ERROR_IS_OK(result)) {
8986                 TALLOC_FREE(r->out.info);
8987                 return result;
8988         }
8989
8990         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8991                                                r->out.info, r->in.level);
8992         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8993
8994         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8995 }
8996
8997 /****************************************************************
8998  _spoolss_GetPrinterDataEx
8999
9000  From MSDN documentation of GetPrinterDataEx: pass request
9001  to GetPrinterData if key is "PrinterDriverData".
9002 ****************************************************************/
9003
9004 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9005                                  struct spoolss_GetPrinterDataEx *r)
9006 {
9007         POLICY_HND      *handle = r->in.handle;
9008         uint8           *data = NULL;
9009         const char      *keyname = r->in.key_name;
9010         const char      *valuename = r->in.value_name;
9011
9012         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9013
9014         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9015         int                     snum = 0;
9016         WERROR                  status = WERR_OK;
9017
9018         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9019
9020         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9021                 keyname, valuename));
9022
9023         /* in case of problem, return some default values */
9024
9025         *r->out.needed  = 0;
9026         *r->out.type    = 0;
9027
9028         if (!Printer) {
9029                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9030                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9031                 status = WERR_BADFID;
9032                 goto done;
9033         }
9034
9035         /* Is the handle to a printer or to the server? */
9036
9037         if (Printer->printer_type == SPLHND_SERVER) {
9038                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9039                         "Not implemented for server handles yet\n"));
9040                 status = WERR_INVALID_PARAM;
9041                 goto done;
9042         }
9043
9044         if ( !get_printer_snum(p,handle, &snum, NULL) )
9045                 return WERR_BADFID;
9046
9047         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9048         if ( !W_ERROR_IS_OK(status) )
9049                 goto done;
9050
9051         /* check to see if the keyname is valid */
9052         if ( !strlen(keyname) ) {
9053                 status = WERR_INVALID_PARAM;
9054                 goto done;
9055         }
9056
9057         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9058                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9059                         "Invalid keyname [%s]\n", keyname ));
9060                 free_a_printer( &printer, 2 );
9061                 status = WERR_BADFILE;
9062                 goto done;
9063         }
9064
9065         /* When given a new keyname, we should just create it */
9066
9067         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9068                                      r->out.type, &data, r->out.needed,
9069                                      r->in.offered );
9070
9071         if (*r->out.needed > r->in.offered) {
9072                 status = WERR_MORE_DATA;
9073         }
9074
9075         if (W_ERROR_IS_OK(status)) {
9076                 memcpy(r->out.buffer, data, r->in.offered);
9077         }
9078
9079 done:
9080         if ( printer )
9081         free_a_printer( &printer, 2 );
9082
9083         return status;
9084 }
9085
9086 /****************************************************************
9087  _spoolss_SetPrinterDataEx
9088 ****************************************************************/
9089
9090 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9091                                  struct spoolss_SetPrinterDataEx *r)
9092 {
9093         POLICY_HND              *handle = r->in.handle;
9094         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9095         int                     snum = 0;
9096         WERROR                  status = WERR_OK;
9097         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9098         char                    *oid_string;
9099
9100         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9101
9102         /* From MSDN documentation of SetPrinterDataEx: pass request to
9103            SetPrinterData if key is "PrinterDriverData" */
9104
9105         if (!Printer) {
9106                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9107                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9108                 return WERR_BADFID;
9109         }
9110
9111         if ( Printer->printer_type == SPLHND_SERVER ) {
9112                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9113                         "Not implemented for server handles yet\n"));
9114                 return WERR_INVALID_PARAM;
9115         }
9116
9117         if ( !get_printer_snum(p,handle, &snum, NULL) )
9118                 return WERR_BADFID;
9119
9120         /*
9121          * Access check : NT returns "access denied" if you make a
9122          * SetPrinterData call without the necessary privildge.
9123          * we were originally returning OK if nothing changed
9124          * which made Win2k issue **a lot** of SetPrinterData
9125          * when connecting to a printer  --jerry
9126          */
9127
9128         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9129         {
9130                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9131                         "change denied by handle access permissions\n"));
9132                 return WERR_ACCESS_DENIED;
9133         }
9134
9135         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9136         if (!W_ERROR_IS_OK(status))
9137                 return status;
9138
9139         /* check for OID in valuename */
9140
9141         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9142         {
9143                 *oid_string = '\0';
9144                 oid_string++;
9145         }
9146
9147         /* save the registry data */
9148
9149         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9150                                      r->in.type, r->in.buffer, r->in.offered );
9151
9152         if ( W_ERROR_IS_OK(status) )
9153         {
9154                 /* save the OID if one was specified */
9155                 if ( oid_string ) {
9156                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9157                                 r->in.key_name, SPOOL_OID_KEY);
9158                         if (!str) {
9159                                 return WERR_NOMEM;
9160                         }
9161
9162                         /*
9163                          * I'm not checking the status here on purpose.  Don't know
9164                          * if this is right, but I'm returning the status from the
9165                          * previous set_printer_dataex() call.  I have no idea if
9166                          * this is right.    --jerry
9167                          */
9168
9169                         set_printer_dataex( printer, str, r->in.value_name,
9170                                             REG_SZ, (uint8 *)oid_string,
9171                                             strlen(oid_string)+1 );
9172                 }
9173
9174                 status = mod_a_printer(printer, 2);
9175         }
9176
9177         free_a_printer(&printer, 2);
9178
9179         return status;
9180 }
9181
9182 /****************************************************************
9183  _spoolss_DeletePrinterDataEx
9184 ****************************************************************/
9185
9186 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9187                                     struct spoolss_DeletePrinterDataEx *r)
9188 {
9189         POLICY_HND      *handle = r->in.handle;
9190         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9191         int             snum=0;
9192         WERROR          status = WERR_OK;
9193         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9194
9195         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9196
9197         if (!Printer) {
9198                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9199                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9200                 return WERR_BADFID;
9201         }
9202
9203         if (!get_printer_snum(p, handle, &snum, NULL))
9204                 return WERR_BADFID;
9205
9206         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9207                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9208                         "printer properties change denied by handle\n"));
9209                 return WERR_ACCESS_DENIED;
9210         }
9211
9212         if (!r->in.value_name || !r->in.key_name) {
9213                 return WERR_NOMEM;
9214         }
9215
9216         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9217         if (!W_ERROR_IS_OK(status))
9218                 return status;
9219
9220         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9221
9222         if ( W_ERROR_IS_OK(status) )
9223                 mod_a_printer( printer, 2 );
9224
9225         free_a_printer(&printer, 2);
9226
9227         return status;
9228 }
9229
9230 /********************************************************************
9231  * spoolss_enumprinterkey
9232  ********************************************************************/
9233
9234
9235 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9236 {
9237         fstring         key;
9238         fstring         *keynames = NULL;
9239         uint16          *enumkeys = NULL;
9240         int             num_keys;
9241         int             printerkey_len;
9242         POLICY_HND      *handle = &q_u->handle;
9243         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9244         NT_PRINTER_DATA *data;
9245         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9246         int             snum = 0;
9247         WERROR          status = WERR_BADFILE;
9248
9249
9250         DEBUG(4,("_spoolss_enumprinterkey\n"));
9251
9252         if (!Printer) {
9253                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9254                 return WERR_BADFID;
9255         }
9256
9257         if ( !get_printer_snum(p,handle, &snum, NULL) )
9258                 return WERR_BADFID;
9259
9260         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9261         if (!W_ERROR_IS_OK(status))
9262                 return status;
9263
9264         /* get the list of subkey names */
9265
9266         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9267         data = printer->info_2->data;
9268
9269         num_keys = get_printer_subkeys( data, key, &keynames );
9270
9271         if ( num_keys == -1 ) {
9272                 status = WERR_BADFILE;
9273                 goto done;
9274         }
9275
9276         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9277
9278         r_u->needed = printerkey_len*2;
9279
9280         if ( q_u->size < r_u->needed ) {
9281                 status = WERR_MORE_DATA;
9282                 goto done;
9283         }
9284
9285         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9286                 status = WERR_NOMEM;
9287                 goto done;
9288         }
9289
9290         status = WERR_OK;
9291
9292         if ( q_u->size < r_u->needed )
9293                 status = WERR_MORE_DATA;
9294
9295 done:
9296         free_a_printer( &printer, 2 );
9297         SAFE_FREE( keynames );
9298
9299         return status;
9300 }
9301
9302 /****************************************************************
9303  _spoolss_DeletePrinterKey
9304 ****************************************************************/
9305
9306 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9307                                  struct spoolss_DeletePrinterKey *r)
9308 {
9309         POLICY_HND              *handle = r->in.handle;
9310         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9311         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9312         int                     snum=0;
9313         WERROR                  status;
9314
9315         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9316
9317         if (!Printer) {
9318                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9319                         OUR_HANDLE(handle)));
9320                 return WERR_BADFID;
9321         }
9322
9323         /* if keyname == NULL, return error */
9324
9325         if ( !r->in.key_name )
9326                 return WERR_INVALID_PARAM;
9327
9328         if (!get_printer_snum(p, handle, &snum, NULL))
9329                 return WERR_BADFID;
9330
9331         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9332                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9333                         "printer properties change denied by handle\n"));
9334                 return WERR_ACCESS_DENIED;
9335         }
9336
9337         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9338         if (!W_ERROR_IS_OK(status))
9339                 return status;
9340
9341         /* delete the key and all subneys */
9342
9343         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9344
9345         if ( W_ERROR_IS_OK(status) )
9346                 status = mod_a_printer(printer, 2);
9347
9348         free_a_printer( &printer, 2 );
9349
9350         return status;
9351 }
9352
9353
9354 /********************************************************************
9355  * spoolss_enumprinterdataex
9356  ********************************************************************/
9357
9358 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9359 {
9360         POLICY_HND      *handle = &q_u->handle;
9361         uint32          in_size = q_u->size;
9362         uint32          num_entries,
9363                         needed;
9364         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9365         PRINTER_ENUM_VALUES     *enum_values = NULL;
9366         NT_PRINTER_DATA         *p_data;
9367         fstring         key;
9368         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9369         int             snum;
9370         WERROR          result;
9371         int             key_index;
9372         int             i;
9373         REGISTRY_VALUE  *val;
9374         char            *value_name;
9375         uint32          data_len;
9376
9377
9378         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9379
9380         if (!Printer) {
9381                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9382                 return WERR_BADFID;
9383         }
9384
9385         /*
9386          * first check for a keyname of NULL or "".  Win2k seems to send
9387          * this a lot and we should send back WERR_INVALID_PARAM
9388          * no need to spend time looking up the printer in this case.
9389          * --jerry
9390          */
9391
9392         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9393         if ( !strlen(key) ) {
9394                 result = WERR_INVALID_PARAM;
9395                 goto done;
9396         }
9397
9398         /* get the printer off of disk */
9399
9400         if (!get_printer_snum(p,handle, &snum, NULL))
9401                 return WERR_BADFID;
9402
9403         ZERO_STRUCT(printer);
9404         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9405         if (!W_ERROR_IS_OK(result))
9406                 return result;
9407
9408         /* now look for a match on the key name */
9409
9410         p_data = printer->info_2->data;
9411
9412         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9413         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9414         {
9415                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9416                 result = WERR_INVALID_PARAM;
9417                 goto done;
9418         }
9419
9420         result = WERR_OK;
9421         needed = 0;
9422
9423         /* allocate the memory for the array of pointers -- if necessary */
9424
9425         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9426         if ( num_entries )
9427         {
9428                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9429                 {
9430                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9431                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9432                         result = WERR_NOMEM;
9433                         goto done;
9434                 }
9435
9436                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9437         }
9438
9439         /*
9440          * loop through all params and build the array to pass
9441          * back to the  client
9442          */
9443
9444         for ( i=0; i<num_entries; i++ )
9445         {
9446                 /* lookup the registry value */
9447
9448                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9449                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9450
9451                 /* copy the data */
9452
9453                 value_name = regval_name( val );
9454                 init_unistr( &enum_values[i].valuename, value_name );
9455                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9456                 enum_values[i].type      = regval_type( val );
9457
9458                 data_len = regval_size( val );
9459                 if ( data_len ) {
9460                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9461                         {
9462                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9463                                         data_len ));
9464                                 result = WERR_NOMEM;
9465                                 goto done;
9466                         }
9467                 }
9468                 enum_values[i].data_len = data_len;
9469
9470                 /* keep track of the size of the array in bytes */
9471
9472                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9473         }
9474
9475         /* housekeeping information in the reply */
9476
9477         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9478          * the hand marshalled container size is a multiple
9479          * of 4 bytes for RPC alignment.
9480          */
9481
9482         if (needed % 4) {
9483                 needed += 4-(needed % 4);
9484         }
9485
9486         r_u->needed     = needed;
9487         r_u->returned   = num_entries;
9488
9489         if (needed > in_size) {
9490                 result = WERR_MORE_DATA;
9491                 goto done;
9492         }
9493
9494         /* copy data into the reply */
9495
9496         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9497            response buffer size is != the offered buffer size
9498
9499                 r_u->ctr.size           = r_u->needed;
9500         */
9501         r_u->ctr.size           = in_size;
9502
9503         r_u->ctr.size_of_array  = r_u->returned;
9504         r_u->ctr.values         = enum_values;
9505
9506 done:
9507         if ( printer )
9508         free_a_printer(&printer, 2);
9509
9510         return result;
9511 }
9512
9513 /****************************************************************************
9514 ****************************************************************************/
9515
9516 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9517                                                  const char *servername,
9518                                                  const char *environment,
9519                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9520 {
9521         WERROR werr;
9522         char *path = NULL;
9523
9524         werr = compose_spoolss_server_path(mem_ctx,
9525                                            servername,
9526                                            environment,
9527                                            SPOOLSS_PRTPROCS_PATH,
9528                                            &path);
9529         if (!W_ERROR_IS_OK(werr)) {
9530                 return werr;
9531         }
9532
9533         DEBUG(4,("print processor directory: [%s]\n", path));
9534
9535         r->directory_name = path;
9536
9537         return WERR_OK;
9538 }
9539
9540 /****************************************************************
9541  _spoolss_GetPrintProcessorDirectory
9542 ****************************************************************/
9543
9544 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9545                                            struct spoolss_GetPrintProcessorDirectory *r)
9546 {
9547         WERROR result;
9548
9549         /* that's an [in out] buffer */
9550
9551         if (!r->in.buffer && (r->in.offered != 0)) {
9552                 return WERR_INVALID_PARAM;
9553         }
9554
9555         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9556                 r->in.level));
9557
9558         *r->out.needed = 0;
9559
9560         /* r->in.level is ignored */
9561
9562         result = getprintprocessordirectory_level_1(p->mem_ctx,
9563                                                     r->in.server,
9564                                                     r->in.environment,
9565                                                     &r->out.info->info1);
9566         if (!W_ERROR_IS_OK(result)) {
9567                 TALLOC_FREE(r->out.info);
9568                 return result;
9569         }
9570
9571         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9572                                                r->out.info, r->in.level);
9573         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9574
9575         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9576 }
9577
9578 /*******************************************************************
9579  ********************************************************************/
9580
9581 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9582                                const char *dllname)
9583 {
9584         enum ndr_err_code ndr_err;
9585         struct spoolss_MonitorUi ui;
9586
9587         ui.dll_name = dllname;
9588
9589         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9590                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9591         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9592                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9593         }
9594         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9595 }
9596
9597 /*******************************************************************
9598  Streams the monitor UI DLL name in UNICODE
9599 *******************************************************************/
9600
9601 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9602                                NT_USER_TOKEN *token, DATA_BLOB *in,
9603                                DATA_BLOB *out, uint32_t *needed)
9604 {
9605         const char *dllname = "tcpmonui.dll";
9606
9607         *needed = (strlen(dllname)+1) * 2;
9608
9609         if (out->length < *needed) {
9610                 return WERR_INSUFFICIENT_BUFFER;
9611         }
9612
9613         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9614                 return WERR_NOMEM;
9615         }
9616
9617         return WERR_OK;
9618 }
9619
9620 /*******************************************************************
9621  ********************************************************************/
9622
9623 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9624                              struct spoolss_PortData1 *port1,
9625                              const DATA_BLOB *buf)
9626 {
9627         enum ndr_err_code ndr_err;
9628         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9629                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9630         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9631                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9632         }
9633         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9634 }
9635
9636 /*******************************************************************
9637  ********************************************************************/
9638
9639 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9640                              struct spoolss_PortData2 *port2,
9641                              const DATA_BLOB *buf)
9642 {
9643         enum ndr_err_code ndr_err;
9644         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9645                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9646         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9647                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9648         }
9649         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9650 }
9651
9652 /*******************************************************************
9653  Create a new TCP/IP port
9654 *******************************************************************/
9655
9656 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9657                              NT_USER_TOKEN *token, DATA_BLOB *in,
9658                              DATA_BLOB *out, uint32_t *needed)
9659 {
9660         struct spoolss_PortData1 port1;
9661         struct spoolss_PortData2 port2;
9662         char *device_uri = NULL;
9663         uint32_t version;
9664
9665         const char *portname;
9666         const char *hostaddress;
9667         const char *queue;
9668         uint32_t port_number;
9669         uint32_t protocol;
9670
9671         /* peek for spoolss_PortData version */
9672
9673         if (!in || (in->length < (128 + 4))) {
9674                 return WERR_GENERAL_FAILURE;
9675         }
9676
9677         version = IVAL(in->data, 128);
9678
9679         switch (version) {
9680                 case 1:
9681                         ZERO_STRUCT(port1);
9682
9683                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9684                                 return WERR_NOMEM;
9685                         }
9686
9687                         portname        = port1.portname;
9688                         hostaddress     = port1.hostaddress;
9689                         queue           = port1.queue;
9690                         protocol        = port1.protocol;
9691                         port_number     = port1.port_number;
9692
9693                         break;
9694                 case 2:
9695                         ZERO_STRUCT(port2);
9696
9697                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9698                                 return WERR_NOMEM;
9699                         }
9700
9701                         portname        = port2.portname;
9702                         hostaddress     = port2.hostaddress;
9703                         queue           = port2.queue;
9704                         protocol        = port2.protocol;
9705                         port_number     = port2.port_number;
9706
9707                         break;
9708                 default:
9709                         DEBUG(1,("xcvtcp_addport: "
9710                                 "unknown version of port_data: %d\n", version));
9711                         return WERR_UNKNOWN_PORT;
9712         }
9713
9714         /* create the device URI and call the add_port_hook() */
9715
9716         switch (protocol) {
9717         case PROTOCOL_RAWTCP_TYPE:
9718                 device_uri = talloc_asprintf(mem_ctx,
9719                                 "socket://%s:%d/", hostaddress,
9720                                 port_number);
9721                 break;
9722
9723         case PROTOCOL_LPR_TYPE:
9724                 device_uri = talloc_asprintf(mem_ctx,
9725                         "lpr://%s/%s", hostaddress, queue );
9726                 break;
9727
9728         default:
9729                 return WERR_UNKNOWN_PORT;
9730         }
9731
9732         if (!device_uri) {
9733                 return WERR_NOMEM;
9734         }
9735
9736         return add_port_hook(mem_ctx, token, portname, device_uri);
9737 }
9738
9739 /*******************************************************************
9740 *******************************************************************/
9741
9742 struct xcv_api_table xcvtcp_cmds[] = {
9743         { "MonitorUI",  xcvtcp_monitorui },
9744         { "AddPort",    xcvtcp_addport},
9745         { NULL,         NULL }
9746 };
9747
9748 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9749                                      NT_USER_TOKEN *token, const char *command,
9750                                      DATA_BLOB *inbuf,
9751                                      DATA_BLOB *outbuf,
9752                                      uint32_t *needed )
9753 {
9754         int i;
9755
9756         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9757
9758         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9759                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9760                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9761         }
9762
9763         return WERR_BADFUNC;
9764 }
9765
9766 /*******************************************************************
9767 *******************************************************************/
9768 #if 0   /* don't support management using the "Local Port" monitor */
9769
9770 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9771                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9772                                  DATA_BLOB *out, uint32_t *needed)
9773 {
9774         const char *dllname = "localui.dll";
9775
9776         *needed = (strlen(dllname)+1) * 2;
9777
9778         if (out->length < *needed) {
9779                 return WERR_INSUFFICIENT_BUFFER;
9780         }
9781
9782         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9783                 return WERR_NOMEM;
9784         }
9785
9786         return WERR_OK;
9787 }
9788
9789 /*******************************************************************
9790 *******************************************************************/
9791
9792 struct xcv_api_table xcvlocal_cmds[] = {
9793         { "MonitorUI",  xcvlocal_monitorui },
9794         { NULL,         NULL }
9795 };
9796 #else
9797 struct xcv_api_table xcvlocal_cmds[] = {
9798         { NULL,         NULL }
9799 };
9800 #endif
9801
9802
9803
9804 /*******************************************************************
9805 *******************************************************************/
9806
9807 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9808                                        NT_USER_TOKEN *token, const char *command,
9809                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9810                                        uint32_t *needed)
9811 {
9812         int i;
9813
9814         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9815
9816         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9817                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9818                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9819         }
9820         return WERR_BADFUNC;
9821 }
9822
9823 /****************************************************************
9824  _spoolss_XcvData
9825 ****************************************************************/
9826
9827 WERROR _spoolss_XcvData(pipes_struct *p,
9828                         struct spoolss_XcvData *r)
9829 {
9830         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9831         DATA_BLOB out_data = data_blob_null;
9832         WERROR werror;
9833
9834         if (!Printer) {
9835                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9836                         OUR_HANDLE(r->in.handle)));
9837                 return WERR_BADFID;
9838         }
9839
9840         /* Has to be a handle to the TCP/IP port monitor */
9841
9842         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9843                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9844                 return WERR_BADFID;
9845         }
9846
9847         /* requires administrative access to the server */
9848
9849         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9850                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9851                 return WERR_ACCESS_DENIED;
9852         }
9853
9854         /* Allocate the outgoing buffer */
9855
9856         if (r->in.out_data_size) {
9857                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9858                 if (out_data.data == NULL) {
9859                         return WERR_NOMEM;
9860                 }
9861         }
9862
9863         switch ( Printer->printer_type ) {
9864         case SPLHND_PORTMON_TCP:
9865                 werror = process_xcvtcp_command(p->mem_ctx,
9866                                                 p->server_info->ptok,
9867                                                 r->in.function_name,
9868                                                 &r->in.in_data, &out_data,
9869                                                 r->out.needed);
9870                 break;
9871         case SPLHND_PORTMON_LOCAL:
9872                 werror = process_xcvlocal_command(p->mem_ctx,
9873                                                   p->server_info->ptok,
9874                                                   r->in.function_name,
9875                                                   &r->in.in_data, &out_data,
9876                                                   r->out.needed);
9877                 break;
9878         default:
9879                 werror = WERR_INVALID_PRINT_MONITOR;
9880         }
9881
9882         if (!W_ERROR_IS_OK(werror)) {
9883                 return werror;
9884         }
9885
9886         *r->out.status_code = 0;
9887
9888         memcpy(r->out.out_data, out_data.data, out_data.length);
9889
9890         return WERR_OK;
9891 }
9892
9893 /****************************************************************
9894  _spoolss_AddPrintProcessor
9895 ****************************************************************/
9896
9897 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9898                                   struct spoolss_AddPrintProcessor *r)
9899 {
9900         /* for now, just indicate success and ignore the add.  We'll
9901            automatically set the winprint processor for printer
9902            entries later.  Used to debug the LexMark Optra S 1855 PCL
9903            driver --jerry */
9904
9905         return WERR_OK;
9906 }
9907
9908 /****************************************************************
9909  _spoolss_AddPrinter
9910 ****************************************************************/
9911
9912 WERROR _spoolss_AddPrinter(pipes_struct *p,
9913                            struct spoolss_AddPrinter *r)
9914 {
9915         p->rng_fault_state = true;
9916         return WERR_NOT_SUPPORTED;
9917 }
9918
9919 /****************************************************************
9920  _spoolss_GetPrinterDriver
9921 ****************************************************************/
9922
9923 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9924                                  struct spoolss_GetPrinterDriver *r)
9925 {
9926         p->rng_fault_state = true;
9927         return WERR_NOT_SUPPORTED;
9928 }
9929
9930 /****************************************************************
9931  _spoolss_ReadPrinter
9932 ****************************************************************/
9933
9934 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9935                             struct spoolss_ReadPrinter *r)
9936 {
9937         p->rng_fault_state = true;
9938         return WERR_NOT_SUPPORTED;
9939 }
9940
9941 /****************************************************************
9942  _spoolss_SetPrinterData
9943 ****************************************************************/
9944
9945 WERROR _spoolss_SetPrinterData(pipes_struct *p,
9946                                struct spoolss_SetPrinterData *r)
9947 {
9948         p->rng_fault_state = true;
9949         return WERR_NOT_SUPPORTED;
9950 }
9951
9952 /****************************************************************
9953  _spoolss_WaitForPrinterChange
9954 ****************************************************************/
9955
9956 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9957                                      struct spoolss_WaitForPrinterChange *r)
9958 {
9959         p->rng_fault_state = true;
9960         return WERR_NOT_SUPPORTED;
9961 }
9962
9963 /****************************************************************
9964  _spoolss_AddPort
9965 ****************************************************************/
9966
9967 WERROR _spoolss_AddPort(pipes_struct *p,
9968                         struct spoolss_AddPort *r)
9969 {
9970         p->rng_fault_state = true;
9971         return WERR_NOT_SUPPORTED;
9972 }
9973
9974 /****************************************************************
9975  _spoolss_ConfigurePort
9976 ****************************************************************/
9977
9978 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9979                               struct spoolss_ConfigurePort *r)
9980 {
9981         p->rng_fault_state = true;
9982         return WERR_NOT_SUPPORTED;
9983 }
9984
9985 /****************************************************************
9986  _spoolss_DeletePort
9987 ****************************************************************/
9988
9989 WERROR _spoolss_DeletePort(pipes_struct *p,
9990                            struct spoolss_DeletePort *r)
9991 {
9992         p->rng_fault_state = true;
9993         return WERR_NOT_SUPPORTED;
9994 }
9995
9996 /****************************************************************
9997  _spoolss_CreatePrinterIC
9998 ****************************************************************/
9999
10000 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10001                                 struct spoolss_CreatePrinterIC *r)
10002 {
10003         p->rng_fault_state = true;
10004         return WERR_NOT_SUPPORTED;
10005 }
10006
10007 /****************************************************************
10008  _spoolss_PlayGDIScriptOnPrinterIC
10009 ****************************************************************/
10010
10011 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10012                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10013 {
10014         p->rng_fault_state = true;
10015         return WERR_NOT_SUPPORTED;
10016 }
10017
10018 /****************************************************************
10019  _spoolss_DeletePrinterIC
10020 ****************************************************************/
10021
10022 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10023                                 struct spoolss_DeletePrinterIC *r)
10024 {
10025         p->rng_fault_state = true;
10026         return WERR_NOT_SUPPORTED;
10027 }
10028
10029 /****************************************************************
10030  _spoolss_AddPrinterConnection
10031 ****************************************************************/
10032
10033 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10034                                      struct spoolss_AddPrinterConnection *r)
10035 {
10036         p->rng_fault_state = true;
10037         return WERR_NOT_SUPPORTED;
10038 }
10039
10040 /****************************************************************
10041  _spoolss_DeletePrinterConnection
10042 ****************************************************************/
10043
10044 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10045                                         struct spoolss_DeletePrinterConnection *r)
10046 {
10047         p->rng_fault_state = true;
10048         return WERR_NOT_SUPPORTED;
10049 }
10050
10051 /****************************************************************
10052  _spoolss_PrinterMessageBox
10053 ****************************************************************/
10054
10055 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10056                                   struct spoolss_PrinterMessageBox *r)
10057 {
10058         p->rng_fault_state = true;
10059         return WERR_NOT_SUPPORTED;
10060 }
10061
10062 /****************************************************************
10063  _spoolss_AddMonitor
10064 ****************************************************************/
10065
10066 WERROR _spoolss_AddMonitor(pipes_struct *p,
10067                            struct spoolss_AddMonitor *r)
10068 {
10069         p->rng_fault_state = true;
10070         return WERR_NOT_SUPPORTED;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_DeleteMonitor
10075 ****************************************************************/
10076
10077 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10078                               struct spoolss_DeleteMonitor *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085  _spoolss_DeletePrintProcessor
10086 ****************************************************************/
10087
10088 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10089                                      struct spoolss_DeletePrintProcessor *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_AddPrintProvidor
10097 ****************************************************************/
10098
10099 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10100                                  struct spoolss_AddPrintProvidor *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107  _spoolss_DeletePrintProvidor
10108 ****************************************************************/
10109
10110 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10111                                     struct spoolss_DeletePrintProvidor *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118  _spoolss_FindFirstPrinterChangeNotification
10119 ****************************************************************/
10120
10121 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10122                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_FindNextPrinterChangeNotification
10130 ****************************************************************/
10131
10132 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10133                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10141 ****************************************************************/
10142
10143 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10144                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151  _spoolss_ReplyOpenPrinter
10152 ****************************************************************/
10153
10154 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10155                                  struct spoolss_ReplyOpenPrinter *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162  _spoolss_RouterReplyPrinter
10163 ****************************************************************/
10164
10165 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10166                                    struct spoolss_RouterReplyPrinter *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173  _spoolss_ReplyClosePrinter
10174 ****************************************************************/
10175
10176 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10177                                   struct spoolss_ReplyClosePrinter *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_AddPortEx
10185 ****************************************************************/
10186
10187 WERROR _spoolss_AddPortEx(pipes_struct *p,
10188                           struct spoolss_AddPortEx *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195  _spoolss_RouterFindFirstPrinterChangeNotification
10196 ****************************************************************/
10197
10198 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10199                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206  _spoolss_SpoolerInit
10207 ****************************************************************/
10208
10209 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10210                             struct spoolss_SpoolerInit *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217  _spoolss_ResetPrinterEx
10218 ****************************************************************/
10219
10220 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10221                                struct spoolss_ResetPrinterEx *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228  _spoolss_RouterReplyPrinterEx
10229 ****************************************************************/
10230
10231 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10232                                      struct spoolss_RouterReplyPrinterEx *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239  _spoolss_44
10240 ****************************************************************/
10241
10242 WERROR _spoolss_44(pipes_struct *p,
10243                    struct spoolss_44 *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250  _spoolss_47
10251 ****************************************************************/
10252
10253 WERROR _spoolss_47(pipes_struct *p,
10254                    struct spoolss_47 *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_EnumPrinterData
10262 ****************************************************************/
10263
10264 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10265                                 struct spoolss_EnumPrinterData *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272  _spoolss_4a
10273 ****************************************************************/
10274
10275 WERROR _spoolss_4a(pipes_struct *p,
10276                    struct spoolss_4a *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283  _spoolss_4b
10284 ****************************************************************/
10285
10286 WERROR _spoolss_4b(pipes_struct *p,
10287                    struct spoolss_4b *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294  _spoolss_4c
10295 ****************************************************************/
10296
10297 WERROR _spoolss_4c(pipes_struct *p,
10298                    struct spoolss_4c *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305  _spoolss_EnumPrinterDataEx
10306 ****************************************************************/
10307
10308 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10309                                   struct spoolss_EnumPrinterDataEx *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316  _spoolss_EnumPrinterKey
10317 ****************************************************************/
10318
10319 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10320                                struct spoolss_EnumPrinterKey *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_53
10328 ****************************************************************/
10329
10330 WERROR _spoolss_53(pipes_struct *p,
10331                    struct spoolss_53 *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_55
10339 ****************************************************************/
10340
10341 WERROR _spoolss_55(pipes_struct *p,
10342                    struct spoolss_55 *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }
10347
10348 /****************************************************************
10349  _spoolss_56
10350 ****************************************************************/
10351
10352 WERROR _spoolss_56(pipes_struct *p,
10353                    struct spoolss_56 *r)
10354 {
10355         p->rng_fault_state = true;
10356         return WERR_NOT_SUPPORTED;
10357 }
10358
10359 /****************************************************************
10360  _spoolss_57
10361 ****************************************************************/
10362
10363 WERROR _spoolss_57(pipes_struct *p,
10364                    struct spoolss_57 *r)
10365 {
10366         p->rng_fault_state = true;
10367         return WERR_NOT_SUPPORTED;
10368 }
10369
10370 /****************************************************************
10371  _spoolss_5a
10372 ****************************************************************/
10373
10374 WERROR _spoolss_5a(pipes_struct *p,
10375                    struct spoolss_5a *r)
10376 {
10377         p->rng_fault_state = true;
10378         return WERR_NOT_SUPPORTED;
10379 }
10380
10381 /****************************************************************
10382  _spoolss_5b
10383 ****************************************************************/
10384
10385 WERROR _spoolss_5b(pipes_struct *p,
10386                    struct spoolss_5b *r)
10387 {
10388         p->rng_fault_state = true;
10389         return WERR_NOT_SUPPORTED;
10390 }
10391
10392 /****************************************************************
10393  _spoolss_5c
10394 ****************************************************************/
10395
10396 WERROR _spoolss_5c(pipes_struct *p,
10397                    struct spoolss_5c *r)
10398 {
10399         p->rng_fault_state = true;
10400         return WERR_NOT_SUPPORTED;
10401 }
10402
10403 /****************************************************************
10404  _spoolss_5d
10405 ****************************************************************/
10406
10407 WERROR _spoolss_5d(pipes_struct *p,
10408                    struct spoolss_5d *r)
10409 {
10410         p->rng_fault_state = true;
10411         return WERR_NOT_SUPPORTED;
10412 }
10413
10414 /****************************************************************
10415  _spoolss_5e
10416 ****************************************************************/
10417
10418 WERROR _spoolss_5e(pipes_struct *p,
10419                    struct spoolss_5e *r)
10420 {
10421         p->rng_fault_state = true;
10422         return WERR_NOT_SUPPORTED;
10423 }
10424
10425 /****************************************************************
10426  _spoolss_5f
10427 ****************************************************************/
10428
10429 WERROR _spoolss_5f(pipes_struct *p,
10430                    struct spoolss_5f *r)
10431 {
10432         p->rng_fault_state = true;
10433         return WERR_NOT_SUPPORTED;
10434 }
10435