s3-spoolss: rename convert_printer_info_new to convert_printer_info.
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32         ((info)?ndr_size_##fn(info, level, ic, 0):0)
33
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
36
37 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
38
39
40 extern userdom_struct current_user_info;
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_RPC_SRV
44
45 #ifndef MAX_OPEN_PRINTER_EXS
46 #define MAX_OPEN_PRINTER_EXS 50
47 #endif
48
49 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
50 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
51
52 struct table_node {
53         const char    *long_archi;
54         const char    *short_archi;
55         int     version;
56 };
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32 counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32 smb_connections=0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected==True) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected=False;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
231 {
232         Printer_entry *find_printer = NULL;
233
234         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
235                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
236                 return NULL;
237         }
238
239         return find_printer;
240 }
241
242 /****************************************************************************
243  Close printer index by handle.
244 ****************************************************************************/
245
246 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
247 {
248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249
250         if (!Printer) {
251                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
252                 return False;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return True;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
265 {
266         char *cmd = lp_deleteprinter_cmd();
267         char *command = NULL;
268         int ret;
269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
270         bool is_print_op = False;
271
272         /* can't fail if we don't try */
273
274         if ( !*cmd )
275                 return WERR_OK;
276
277         command = talloc_asprintf(ctx,
278                         "%s \"%s\"",
279                         cmd, sharename);
280         if (!command) {
281                 return WERR_NOMEM;
282         }
283         if ( token )
284                 is_print_op = user_has_privileges( token, &se_printop );
285
286         DEBUG(10,("Running [%s]\n", command));
287
288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290         if ( is_print_op )
291                 become_root();
292
293         if ( (ret = smbrun(command, NULL)) == 0 ) {
294                 /* Tell everyone we updated smb.conf. */
295                 message_send_all(smbd_messaging_context(),
296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
297         }
298
299         if ( is_print_op )
300                 unbecome_root();
301
302         /********** END SePrintOperatorPrivlege BLOCK **********/
303
304         DEBUGADD(10,("returned [%d]\n", ret));
305
306         TALLOC_FREE(command);
307
308         if (ret != 0)
309                 return WERR_BADFID; /* What to return here? */
310
311         /* go ahead and re-read the services immediately */
312         reload_services( False );
313
314         if ( lp_servicenumber( sharename )  < 0 )
315                 return WERR_ACCESS_DENIED;
316
317         return WERR_OK;
318 }
319
320 /****************************************************************************
321  Delete a printer given a handle.
322 ****************************************************************************/
323
324 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
325 {
326         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
327
328         if (!Printer) {
329                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
330                 return WERR_BADFID;
331         }
332
333         /*
334          * It turns out that Windows allows delete printer on a handle
335          * opened by an admin user, then used on a pipe handle created
336          * by an anonymous user..... but they're working on security.... riiight !
337          * JRA.
338          */
339
340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
341                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
342                 return WERR_ACCESS_DENIED;
343         }
344
345         /* this does not need a become root since the access check has been
346            done on the handle already */
347
348         if (del_a_printer( Printer->sharename ) != 0) {
349                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
350                 return WERR_BADFID;
351         }
352
353         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
354                                    Printer->sharename );
355 }
356
357 /****************************************************************************
358  Return the snum of a printer corresponding to an handle.
359 ****************************************************************************/
360
361 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
362                              struct share_params **params)
363 {
364         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368                 return False;
369         }
370
371         switch (Printer->printer_type) {
372                 case SPLHND_PRINTER:
373                         DEBUG(4,("short name:%s\n", Printer->sharename));
374                         *number = print_queue_snum(Printer->sharename);
375                         return (*number != -1);
376                 case SPLHND_SERVER:
377                         return False;
378                 default:
379                         return False;
380         }
381 }
382
383 /****************************************************************************
384  Set printer handle type.
385  Check if it's \\server or \\server\printer
386 ****************************************************************************/
387
388 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
389 {
390         DEBUG(3,("Setting printer type=%s\n", handlename));
391
392         if ( strlen(handlename) < 3 ) {
393                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
394                 return False;
395         }
396
397         /* it's a print server */
398         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
399                 DEBUGADD(4,("Printer is a print server\n"));
400                 Printer->printer_type = SPLHND_SERVER;
401         }
402         /* it's a printer (set_printer_hnd_name() will handle port monitors */
403         else {
404                 DEBUGADD(4,("Printer is a printer\n"));
405                 Printer->printer_type = SPLHND_PRINTER;
406         }
407
408         return True;
409 }
410
411 /****************************************************************************
412  Set printer handle name..  Accept names like \\server, \\server\printer,
413  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
414  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
415  XcvDataPort() interface.
416 ****************************************************************************/
417
418 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
419 {
420         int snum;
421         int n_services=lp_numservices();
422         char *aprinter, *printername;
423         const char *servername;
424         fstring sname;
425         bool found=False;
426         NT_PRINTER_INFO_LEVEL *printer = NULL;
427         WERROR result;
428
429         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
430
431         aprinter = handlename;
432         if ( *handlename == '\\' ) {
433                 servername = canon_servername(handlename);
434                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
435                         *aprinter = '\0';
436                         aprinter++;
437                 }
438         } else {
439                 servername = "";
440         }
441
442         /* save the servername to fill in replies on this handle */
443
444         if ( !is_myname_or_ipaddr( servername ) )
445                 return False;
446
447         fstrcpy( Printer->servername, servername );
448
449         if ( Printer->printer_type == SPLHND_SERVER )
450                 return True;
451
452         if ( Printer->printer_type != SPLHND_PRINTER )
453                 return False;
454
455         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
456
457         /* check for the Port Monitor Interface */
458
459         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
460                 Printer->printer_type = SPLHND_PORTMON_TCP;
461                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
462                 found = True;
463         }
464         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
465                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
466                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
467                 found = True;
468         }
469
470         /* Search all sharenames first as this is easier than pulling
471            the printer_info_2 off of disk. Don't use find_service() since
472            that calls out to map_username() */
473
474         /* do another loop to look for printernames */
475
476         for (snum=0; !found && snum<n_services; snum++) {
477
478                 /* no point going on if this is not a printer */
479
480                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
481                         continue;
482
483                 fstrcpy(sname, lp_servicename(snum));
484                 if ( strequal( aprinter, sname ) ) {
485                         found = True;
486                         break;
487                 }
488
489                 /* no point looking up the printer object if
490                    we aren't allowing printername != sharename */
491
492                 if ( lp_force_printername(snum) )
493                         continue;
494
495                 fstrcpy(sname, lp_servicename(snum));
496
497                 printer = NULL;
498
499                 /* This call doesn't fill in the location or comment from
500                  * a CUPS server for efficiency with large numbers of printers.
501                  * JRA.
502                  */
503
504                 result = get_a_printer_search( NULL, &printer, 2, sname );
505                 if ( !W_ERROR_IS_OK(result) ) {
506                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
507                                 sname, win_errstr(result)));
508                         continue;
509                 }
510
511                 /* printername is always returned as \\server\printername */
512                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
513                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
514                                 printer->info_2->printername));
515                         free_a_printer( &printer, 2);
516                         continue;
517                 }
518
519                 printername++;
520
521                 if ( strequal(printername, aprinter) ) {
522                         free_a_printer( &printer, 2);
523                         found = True;
524                         break;
525                 }
526
527                 DEBUGADD(10, ("printername: %s\n", printername));
528
529                 free_a_printer( &printer, 2);
530         }
531
532         free_a_printer( &printer, 2);
533
534         if ( !found ) {
535                 DEBUGADD(4,("Printer not found\n"));
536                 return False;
537         }
538
539         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
540
541         fstrcpy(Printer->sharename, sname);
542
543         return True;
544 }
545
546 /****************************************************************************
547  Find first available printer slot. creates a printer handle for you.
548  ****************************************************************************/
549
550 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
551 {
552         Printer_entry *new_printer;
553
554         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
555
556         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
557         if (new_printer == NULL) {
558                 return false;
559         }
560         talloc_set_destructor(new_printer, printer_entry_destructor);
561
562         if (!create_policy_hnd(p, hnd, new_printer)) {
563                 TALLOC_FREE(new_printer);
564                 return False;
565         }
566
567         /* Add to the internal list. */
568         DLIST_ADD(printers_list, new_printer);
569
570         new_printer->notify.option=NULL;
571
572         if (!set_printer_hnd_printertype(new_printer, name)) {
573                 close_printer_handle(p, hnd);
574                 return False;
575         }
576
577         if (!set_printer_hnd_name(new_printer, name)) {
578                 close_printer_handle(p, hnd);
579                 return False;
580         }
581
582         new_printer->access_granted = access_granted;
583
584         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585
586         return True;
587 }
588
589 /***************************************************************************
590  check to see if the client motify handle is monitoring the notification
591  given by (notify_type, notify_field).
592  **************************************************************************/
593
594 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
595                                       uint16 notify_field)
596 {
597         return True;
598 }
599
600 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
601                                 uint16 notify_field)
602 {
603         struct spoolss_NotifyOption *option = p->notify.option;
604         uint32 i, j;
605
606         /*
607          * Flags should always be zero when the change notify
608          * is registered by the client's spooler.  A user Win32 app
609          * might use the flags though instead of the NOTIFY_OPTION_INFO
610          * --jerry
611          */
612
613         if (!option) {
614                 return False;
615         }
616
617         if (p->notify.flags)
618                 return is_monitoring_event_flags(
619                         p->notify.flags, notify_type, notify_field);
620
621         for (i = 0; i < option->count; i++) {
622
623                 /* Check match for notify_type */
624
625                 if (option->types[i].type != notify_type)
626                         continue;
627
628                 /* Check match for field */
629
630                 for (j = 0; j < option->types[i].count; j++) {
631                         if (option->types[i].fields[j] == notify_field) {
632                                 return True;
633                         }
634                 }
635         }
636
637         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
638                    p->servername, p->sharename, notify_type, notify_field));
639
640         return False;
641 }
642
643 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
644         _data->data.integer[0] = _integer; \
645         _data->data.integer[1] = 0;
646
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
649         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
650         if (!_data->data.string.string) {\
651                 _data->data.string.size = 0; \
652         } \
653         _data->data.string.size = strlen_m_term(_p) * 2;
654
655 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
656         _data->data.devmode.devmode = _devmode;
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
659         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
660         if (!_data->data.sd.sd) { \
661                 _data->data.sd.sd_size = 0; \
662         } \
663         _data->data.sd.sd_size = _size;
664
665 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
666                                    struct tm *t,
667                                    const char **pp,
668                                    uint32_t *plen)
669 {
670         struct spoolss_Time st;
671         uint32_t len = 16;
672         char *p;
673
674         if (!init_systemtime(&st, t)) {
675                 return;
676         }
677
678         p = talloc_array(mem_ctx, char, len);
679         if (!p) {
680                 return;
681         }
682
683         /*
684          * Systemtime must be linearized as a set of UINT16's.
685          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
686          */
687
688         SSVAL(p, 0, st.year);
689         SSVAL(p, 2, st.month);
690         SSVAL(p, 4, st.day_of_week);
691         SSVAL(p, 6, st.day);
692         SSVAL(p, 8, st.hour);
693         SSVAL(p, 10, st.minute);
694         SSVAL(p, 12, st.second);
695         SSVAL(p, 14, st.millisecond);
696
697         *pp = p;
698         *plen = len;
699 }
700
701 /* Convert a notification message to a struct spoolss_Notify */
702
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704                              struct spoolss_Notify *data,
705                              TALLOC_CTX *mem_ctx)
706 {
707         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
708 }
709
710 static void notify_string(struct spoolss_notify_msg *msg,
711                           struct spoolss_Notify *data,
712                           TALLOC_CTX *mem_ctx)
713 {
714         /* The length of the message includes the trailing \0 */
715
716         data->data.string.size = msg->len * 2;
717         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
718         if (!data->data.string.string) {
719                 data->data.string.size = 0;
720                 return;
721         }
722 }
723
724 static void notify_system_time(struct spoolss_notify_msg *msg,
725                                struct spoolss_Notify *data,
726                                TALLOC_CTX *mem_ctx)
727 {
728         data->data.string.string = NULL;
729         data->data.string.size = 0;
730
731         if (msg->len != sizeof(time_t)) {
732                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
733                           msg->len));
734                 return;
735         }
736
737         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
738                                &data->data.string.string,
739                                &data->data.string.size);
740 }
741
742 struct notify2_message_table {
743         const char *name;
744         void (*fn)(struct spoolss_notify_msg *msg,
745                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
746 };
747
748 static struct notify2_message_table printer_notify_table[] = {
749         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
750         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
751         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
752         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
753         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
754         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
755         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
756         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
757         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
758         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
759         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
760         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
761         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
762         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
763         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
764         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
765         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
766         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
767         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 };
769
770 static struct notify2_message_table job_notify_table[] = {
771         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
772         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
773         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
774         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
775         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
776         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
777         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
778         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
779         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
780         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
781         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
782         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
783         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
784         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
785         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
786         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
787         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
788         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
789         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
790         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
791         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
792         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
793         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
794         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
795 };
796
797
798 /***********************************************************************
799  Allocate talloc context for container object
800  **********************************************************************/
801
802 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 {
804         if ( !ctr )
805                 return;
806
807         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808
809         return;
810 }
811
812 /***********************************************************************
813  release all allocated memory and zero out structure
814  **********************************************************************/
815
816 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
817 {
818         if ( !ctr )
819                 return;
820
821         if ( ctr->ctx )
822                 talloc_destroy(ctr->ctx);
823
824         ZERO_STRUCTP(ctr);
825
826         return;
827 }
828
829 /***********************************************************************
830  **********************************************************************/
831
832 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 {
834         if ( !ctr )
835                 return NULL;
836
837         return ctr->ctx;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 {
845         if ( !ctr || !ctr->msg_groups )
846                 return NULL;
847
848         if ( idx >= ctr->num_groups )
849                 return NULL;
850
851         return &ctr->msg_groups[idx];
852
853 }
854
855 /***********************************************************************
856  How many groups of change messages do we have ?
857  **********************************************************************/
858
859 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 {
861         if ( !ctr )
862                 return 0;
863
864         return ctr->num_groups;
865 }
866
867 /***********************************************************************
868  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
869  **********************************************************************/
870
871 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 {
873         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
874         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
875         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
876         int                             i, new_slot;
877
878         if ( !ctr || !msg )
879                 return 0;
880
881         /* loop over all groups looking for a matching printer name */
882
883         for ( i=0; i<ctr->num_groups; i++ ) {
884                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
885                         break;
886         }
887
888         /* add a new group? */
889
890         if ( i == ctr->num_groups ) {
891                 ctr->num_groups++;
892
893                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
894                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895                         return 0;
896                 }
897                 ctr->msg_groups = groups;
898
899                 /* clear the new entry and set the printer name */
900
901                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
902                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903         }
904
905         /* add the change messages; 'i' is the correct index now regardless */
906
907         msg_grp = &ctr->msg_groups[i];
908
909         msg_grp->num_msgs++;
910
911         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
912                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913                 return 0;
914         }
915         msg_grp->msgs = msg_list;
916
917         new_slot = msg_grp->num_msgs-1;
918         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919
920         /* need to allocate own copy of data */
921
922         if ( msg->len != 0 )
923                 msg_grp->msgs[new_slot].notify.data = (char *)
924                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
925
926         return ctr->num_groups;
927 }
928
929 /***********************************************************************
930  Send a change notication message on all handles which have a call
931  back registered
932  **********************************************************************/
933
934 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
935 {
936         Printer_entry            *p;
937         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
938         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
939         SPOOLSS_NOTIFY_MSG       *messages;
940         int                      sending_msg_count;
941
942         if ( !msg_group ) {
943                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944                 return;
945         }
946
947         messages = msg_group->msgs;
948
949         if ( !messages ) {
950                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951                 return;
952         }
953
954         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
955
956         /* loop over all printers */
957
958         for (p = printers_list; p; p = p->next) {
959                 struct spoolss_Notify *notifies;
960                 uint32_t count = 0;
961                 uint32_t id;
962                 int     i;
963
964                 /* Is there notification on this handle? */
965
966                 if ( !p->notify.client_connected )
967                         continue;
968
969                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
970
971                 /* For this printer?  Print servers always receive
972                    notifications. */
973
974                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
975                     ( !strequal(msg_group->printername, p->sharename) ) )
976                         continue;
977
978                 DEBUG(10,("Our printer\n"));
979
980                 /* allocate the max entries possible */
981
982                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
983                 if (!notifies) {
984                         return;
985                 }
986
987                 /* build the array of change notifications */
988
989                 sending_msg_count = 0;
990
991                 for ( i=0; i<msg_group->num_msgs; i++ ) {
992                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
993
994                         /* Are we monitoring this event? */
995
996                         if (!is_monitoring_event(p, msg->type, msg->field))
997                                 continue;
998
999                         sending_msg_count++;
1000
1001
1002                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1003                                 msg->type, msg->field, p->sharename));
1004
1005                         /*
1006                          * if the is a printer notification handle and not a job notification
1007                          * type, then set the id to 0.  Other wise just use what was specified
1008                          * in the message.
1009                          *
1010                          * When registering change notification on a print server handle
1011                          * we always need to send back the id (snum) matching the printer
1012                          * for which the change took place.  For change notify registered
1013                          * on a printer handle, this does not matter and the id should be 0.
1014                          *
1015                          * --jerry
1016                          */
1017
1018                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019                                 id = 0;
1020                         else
1021                                 id = msg->id;
1022
1023
1024                         /* Convert unix jobid to smb jobid */
1025
1026                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1027                                 id = sysjob_to_jobid(msg->id);
1028
1029                                 if (id == -1) {
1030                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1031                                         goto done;
1032                                 }
1033                         }
1034
1035                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1036
1037                         switch(msg->type) {
1038                         case PRINTER_NOTIFY_TYPE:
1039                                 if ( printer_notify_table[msg->field].fn )
1040                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1041                                 break;
1042
1043                         case JOB_NOTIFY_TYPE:
1044                                 if ( job_notify_table[msg->field].fn )
1045                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1046                                 break;
1047
1048                         default:
1049                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1050                                 goto done;
1051                         }
1052
1053                         count++;
1054                 }
1055
1056                 if ( sending_msg_count ) {
1057                         NTSTATUS status;
1058                         WERROR werr;
1059                         union spoolss_ReplyPrinterInfo info;
1060                         struct spoolss_NotifyInfo info0;
1061                         uint32_t reply_result;
1062
1063                         info0.version   = 0x2;
1064                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1065                         info0.count     = count;
1066                         info0.notifies  = notifies;
1067
1068                         info.info0 = &info0;
1069
1070                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1071                                                                      &p->notify.client_hnd,
1072                                                                      p->notify.change, /* color */
1073                                                                      p->notify.flags,
1074                                                                      &reply_result,
1075                                                                      0, /* reply_type, must be 0 */
1076                                                                      info,
1077                                                                      &werr);
1078                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1079                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1080                                         notify_cli_pipe->srv_name_slash,
1081                                         win_errstr(werr)));
1082                         }
1083                         switch (reply_result) {
1084                                 case 0:
1085                                         break;
1086                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1087                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1088                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1089                                         break;
1090                                 default:
1091                                         break;
1092                         }
1093                 }
1094         }
1095
1096 done:
1097         DEBUG(8,("send_notify2_changes: Exit...\n"));
1098         return;
1099 }
1100
1101 /***********************************************************************
1102  **********************************************************************/
1103
1104 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1105 {
1106
1107         uint32 tv_sec, tv_usec;
1108         size_t offset = 0;
1109
1110         /* Unpack message */
1111
1112         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1113                              msg->printer);
1114
1115         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1116                                 &tv_sec, &tv_usec,
1117                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1118
1119         if (msg->len == 0)
1120                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1121                            &msg->notify.value[0], &msg->notify.value[1]);
1122         else
1123                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1124                            &msg->len, &msg->notify.data);
1125
1126         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1127                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1128
1129         tv->tv_sec = tv_sec;
1130         tv->tv_usec = tv_usec;
1131
1132         if (msg->len == 0)
1133                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1134                           msg->notify.value[1]));
1135         else
1136                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1137
1138         return True;
1139 }
1140
1141 /********************************************************************
1142  Receive a notify2 message list
1143  ********************************************************************/
1144
1145 static void receive_notify2_message_list(struct messaging_context *msg,
1146                                          void *private_data,
1147                                          uint32_t msg_type,
1148                                          struct server_id server_id,
1149                                          DATA_BLOB *data)
1150 {
1151         size_t                  msg_count, i;
1152         char                    *buf = (char *)data->data;
1153         char                    *msg_ptr;
1154         size_t                  msg_len;
1155         SPOOLSS_NOTIFY_MSG      notify;
1156         SPOOLSS_NOTIFY_MSG_CTR  messages;
1157         int                     num_groups;
1158
1159         if (data->length < 4) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1161                 return;
1162         }
1163
1164         msg_count = IVAL(buf, 0);
1165         msg_ptr = buf + 4;
1166
1167         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168
1169         if (msg_count == 0) {
1170                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1171                 return;
1172         }
1173
1174         /* initialize the container */
1175
1176         ZERO_STRUCT( messages );
1177         notify_msg_ctr_init( &messages );
1178
1179         /*
1180          * build message groups for each printer identified
1181          * in a change_notify msg.  Remember that a PCN message
1182          * includes the handle returned for the srv_spoolss_replyopenprinter()
1183          * call.  Therefore messages are grouped according to printer handle.
1184          */
1185
1186         for ( i=0; i<msg_count; i++ ) {
1187                 struct timeval msg_tv;
1188
1189                 if (msg_ptr + 4 - buf > data->length) {
1190                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1191                         return;
1192                 }
1193
1194                 msg_len = IVAL(msg_ptr,0);
1195                 msg_ptr += 4;
1196
1197                 if (msg_ptr + msg_len - buf > data->length) {
1198                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1199                         return;
1200                 }
1201
1202                 /* unpack messages */
1203
1204                 ZERO_STRUCT( notify );
1205                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1206                 msg_ptr += msg_len;
1207
1208                 /* add to correct list in container */
1209
1210                 notify_msg_ctr_addmsg( &messages, &notify );
1211
1212                 /* free memory that might have been allocated by notify2_unpack_msg() */
1213
1214                 if ( notify.len != 0 )
1215                         SAFE_FREE( notify.notify.data );
1216         }
1217
1218         /* process each group of messages */
1219
1220         num_groups = notify_msg_ctr_numgroups( &messages );
1221         for ( i=0; i<num_groups; i++ )
1222                 send_notify2_changes( &messages, i );
1223
1224
1225         /* cleanup */
1226
1227         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228
1229         notify_msg_ctr_destroy( &messages );
1230
1231         return;
1232 }
1233
1234 /********************************************************************
1235  Send a message to ourself about new driver being installed
1236  so we can upgrade the information for each printer bound to this
1237  driver
1238  ********************************************************************/
1239
1240 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1241 {
1242         int len = strlen(drivername);
1243
1244         if (!len)
1245                 return False;
1246
1247         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1248                 drivername));
1249
1250         messaging_send_buf(smbd_messaging_context(), procid_self(),
1251                            MSG_PRINTER_DRVUPGRADE,
1252                            (uint8 *)drivername, len+1);
1253
1254         return True;
1255 }
1256
1257 /**********************************************************************
1258  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1259  over all printers, upgrading ones as necessary
1260  **********************************************************************/
1261
1262 void do_drv_upgrade_printer(struct messaging_context *msg,
1263                             void *private_data,
1264                             uint32_t msg_type,
1265                             struct server_id server_id,
1266                             DATA_BLOB *data)
1267 {
1268         fstring drivername;
1269         int snum;
1270         int n_services = lp_numservices();
1271         size_t len;
1272
1273         len = MIN(data->length,sizeof(drivername)-1);
1274         strncpy(drivername, (const char *)data->data, len);
1275
1276         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1277
1278         /* Iterate the printer list */
1279
1280         for (snum=0; snum<n_services; snum++)
1281         {
1282                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1283                 {
1284                         WERROR result;
1285                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1286
1287                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1288                         if (!W_ERROR_IS_OK(result))
1289                                 continue;
1290
1291                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1292                         {
1293                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1294
1295                                 /* all we care about currently is the change_id */
1296
1297                                 result = mod_a_printer(printer, 2);
1298                                 if (!W_ERROR_IS_OK(result)) {
1299                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1300                                                 win_errstr(result)));
1301                                 }
1302                         }
1303
1304                         free_a_printer(&printer, 2);
1305                 }
1306         }
1307
1308         /* all done */
1309 }
1310
1311 /********************************************************************
1312  Update the cache for all printq's with a registered client
1313  connection
1314  ********************************************************************/
1315
1316 void update_monitored_printq_cache( void )
1317 {
1318         Printer_entry *printer = printers_list;
1319         int snum;
1320
1321         /* loop through all printers and update the cache where
1322            client_connected == True */
1323         while ( printer )
1324         {
1325                 if ( (printer->printer_type == SPLHND_PRINTER)
1326                         && printer->notify.client_connected )
1327                 {
1328                         snum = print_queue_snum(printer->sharename);
1329                         print_queue_status( snum, NULL, NULL );
1330                 }
1331
1332                 printer = printer->next;
1333         }
1334
1335         return;
1336 }
1337 /********************************************************************
1338  Send a message to ourself about new driver being installed
1339  so we can upgrade the information for each printer bound to this
1340  driver
1341  ********************************************************************/
1342
1343 static bool srv_spoolss_reset_printerdata(char* drivername)
1344 {
1345         int len = strlen(drivername);
1346
1347         if (!len)
1348                 return False;
1349
1350         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351                 drivername));
1352
1353         messaging_send_buf(smbd_messaging_context(), procid_self(),
1354                            MSG_PRINTERDATA_INIT_RESET,
1355                            (uint8 *)drivername, len+1);
1356
1357         return True;
1358 }
1359
1360 /**********************************************************************
1361  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1362  over all printers, resetting printer data as neessary
1363  **********************************************************************/
1364
1365 void reset_all_printerdata(struct messaging_context *msg,
1366                            void *private_data,
1367                            uint32_t msg_type,
1368                            struct server_id server_id,
1369                            DATA_BLOB *data)
1370 {
1371         fstring drivername;
1372         int snum;
1373         int n_services = lp_numservices();
1374         size_t len;
1375
1376         len = MIN( data->length, sizeof(drivername)-1 );
1377         strncpy( drivername, (const char *)data->data, len );
1378
1379         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1380
1381         /* Iterate the printer list */
1382
1383         for ( snum=0; snum<n_services; snum++ )
1384         {
1385                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1386                 {
1387                         WERROR result;
1388                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1389
1390                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1391                         if ( !W_ERROR_IS_OK(result) )
1392                                 continue;
1393
1394                         /*
1395                          * if the printer is bound to the driver,
1396                          * then reset to the new driver initdata
1397                          */
1398
1399                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1400                         {
1401                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1402
1403                                 if ( !set_driver_init(printer, 2) ) {
1404                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1405                                                 printer->info_2->printername, printer->info_2->drivername));
1406                                 }
1407
1408                                 result = mod_a_printer( printer, 2 );
1409                                 if ( !W_ERROR_IS_OK(result) ) {
1410                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1411                                                 get_dos_error_msg(result)));
1412                                 }
1413                         }
1414
1415                         free_a_printer( &printer, 2 );
1416                 }
1417         }
1418
1419         /* all done */
1420
1421         return;
1422 }
1423
1424 /****************************************************************
1425  _spoolss_OpenPrinter
1426 ****************************************************************/
1427
1428 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1429                             struct spoolss_OpenPrinter *r)
1430 {
1431         struct spoolss_OpenPrinterEx e;
1432         WERROR werr;
1433
1434         ZERO_STRUCT(e.in.userlevel);
1435
1436         e.in.printername        = r->in.printername;
1437         e.in.datatype           = r->in.datatype;
1438         e.in.devmode_ctr        = r->in.devmode_ctr;
1439         e.in.access_mask        = r->in.access_mask;
1440         e.in.level              = 0;
1441
1442         e.out.handle            = r->out.handle;
1443
1444         werr = _spoolss_OpenPrinterEx(p, &e);
1445
1446         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1447                 /* OpenPrinterEx returns this for a bad
1448                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1449                  * instead.
1450                  */
1451                 werr = WERR_INVALID_PRINTER_NAME;
1452         }
1453
1454         return werr;
1455 }
1456
1457 /********************************************************************
1458  ********************************************************************/
1459
1460 bool convert_devicemode(const char *printername,
1461                         const struct spoolss_DeviceMode *devmode,
1462                         NT_DEVICEMODE **pp_nt_devmode)
1463 {
1464         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1465
1466         /*
1467          * Ensure nt_devmode is a valid pointer
1468          * as we will be overwriting it.
1469          */
1470
1471         if (nt_devmode == NULL) {
1472                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1473                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1474                         return false;
1475         }
1476
1477         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1478         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1479
1480         nt_devmode->specversion         = devmode->specversion;
1481         nt_devmode->driverversion       = devmode->driverversion;
1482         nt_devmode->size                = devmode->size;
1483         nt_devmode->fields              = devmode->fields;
1484         nt_devmode->orientation         = devmode->orientation;
1485         nt_devmode->papersize           = devmode->papersize;
1486         nt_devmode->paperlength         = devmode->paperlength;
1487         nt_devmode->paperwidth          = devmode->paperwidth;
1488         nt_devmode->scale               = devmode->scale;
1489         nt_devmode->copies              = devmode->copies;
1490         nt_devmode->defaultsource       = devmode->defaultsource;
1491         nt_devmode->printquality        = devmode->printquality;
1492         nt_devmode->color               = devmode->color;
1493         nt_devmode->duplex              = devmode->duplex;
1494         nt_devmode->yresolution         = devmode->yresolution;
1495         nt_devmode->ttoption            = devmode->ttoption;
1496         nt_devmode->collate             = devmode->collate;
1497
1498         nt_devmode->logpixels           = devmode->logpixels;
1499         nt_devmode->bitsperpel          = devmode->bitsperpel;
1500         nt_devmode->pelswidth           = devmode->pelswidth;
1501         nt_devmode->pelsheight          = devmode->pelsheight;
1502         nt_devmode->displayflags        = devmode->displayflags;
1503         nt_devmode->displayfrequency    = devmode->displayfrequency;
1504         nt_devmode->icmmethod           = devmode->icmmethod;
1505         nt_devmode->icmintent           = devmode->icmintent;
1506         nt_devmode->mediatype           = devmode->mediatype;
1507         nt_devmode->dithertype          = devmode->dithertype;
1508         nt_devmode->reserved1           = devmode->reserved1;
1509         nt_devmode->reserved2           = devmode->reserved2;
1510         nt_devmode->panningwidth        = devmode->panningwidth;
1511         nt_devmode->panningheight       = devmode->panningheight;
1512
1513         /*
1514          * Only change private and driverextra if the incoming devmode
1515          * has a new one. JRA.
1516          */
1517
1518         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1519                 SAFE_FREE(nt_devmode->nt_dev_private);
1520                 nt_devmode->driverextra = devmode->__driverextra_length;
1521                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1522                         return false;
1523                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1524         }
1525
1526         *pp_nt_devmode = nt_devmode;
1527
1528         return true;
1529 }
1530
1531 /****************************************************************
1532  _spoolss_OpenPrinterEx
1533 ****************************************************************/
1534
1535 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1536                               struct spoolss_OpenPrinterEx *r)
1537 {
1538         POLICY_HND              *handle = r->out.handle;
1539         char *name = CONST_DISCARD(char *, r->in.printername);
1540         int snum;
1541         Printer_entry *Printer=NULL;
1542
1543         if (!name) {
1544                 return WERR_INVALID_PARAM;
1545         }
1546
1547         /* some sanity check because you can open a printer or a print server */
1548         /* aka: \\server\printer or \\server */
1549
1550         DEBUGADD(3,("checking name: %s\n",name));
1551
1552         if (!open_printer_hnd(p, handle, name, 0)) {
1553                 ZERO_STRUCTP(r->out.handle);
1554                 return WERR_INVALID_PARAM;
1555         }
1556
1557         Printer=find_printer_index_by_hnd(p, handle);
1558         if ( !Printer ) {
1559                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1560                         "handle we created for printer %s\n", name ));
1561                 close_printer_handle(p,handle);
1562                 ZERO_STRUCTP(r->out.handle);
1563                 return WERR_INVALID_PARAM;
1564         }
1565
1566         /*
1567          * First case: the user is opening the print server:
1568          *
1569          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1570          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571          *
1572          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1573          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1574          * or if the user is listed in the smb.conf printer admin parameter.
1575          *
1576          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1577          * client view printer folder, but does not show the MSAPW.
1578          *
1579          * Note: this test needs code to check access rights here too. Jeremy
1580          * could you look at this?
1581          *
1582          * Second case: the user is opening a printer:
1583          * NT doesn't let us connect to a printer if the connecting user
1584          * doesn't have print permission.
1585          *
1586          * Third case: user is opening a Port Monitor
1587          * access checks same as opening a handle to the print server.
1588          */
1589
1590         switch (Printer->printer_type )
1591         {
1592         case SPLHND_SERVER:
1593         case SPLHND_PORTMON_TCP:
1594         case SPLHND_PORTMON_LOCAL:
1595                 /* Printserver handles use global struct... */
1596
1597                 snum = -1;
1598
1599                 /* Map standard access rights to object specific access rights */
1600
1601                 se_map_standard(&r->in.access_mask,
1602                                 &printserver_std_mapping);
1603
1604                 /* Deny any object specific bits that don't apply to print
1605                    servers (i.e printer and job specific bits) */
1606
1607                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1608
1609                 if (r->in.access_mask &
1610                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1611                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1612                         close_printer_handle(p, handle);
1613                         ZERO_STRUCTP(r->out.handle);
1614                         return WERR_ACCESS_DENIED;
1615                 }
1616
1617                 /* Allow admin access */
1618
1619                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1620                 {
1621                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1622
1623                         if (!lp_ms_add_printer_wizard()) {
1624                                 close_printer_handle(p, handle);
1625                                 ZERO_STRUCTP(r->out.handle);
1626                                 return WERR_ACCESS_DENIED;
1627                         }
1628
1629                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1630                            and not a printer admin, then fail */
1631
1632                         if ((p->server_info->utok.uid != 0) &&
1633                             !user_has_privileges(p->server_info->ptok,
1634                                                  &se_printop ) &&
1635                             !token_contains_name_in_list(
1636                                     uidtoname(p->server_info->utok.uid),
1637                                     NULL, NULL,
1638                                     p->server_info->ptok,
1639                                     lp_printer_admin(snum))) {
1640                                 close_printer_handle(p, handle);
1641                                 ZERO_STRUCTP(r->out.handle);
1642                                 return WERR_ACCESS_DENIED;
1643                         }
1644
1645                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1646                 }
1647                 else
1648                 {
1649                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1650                 }
1651
1652                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1653                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1654
1655                 /* We fall through to return WERR_OK */
1656                 break;
1657
1658         case SPLHND_PRINTER:
1659                 /* NT doesn't let us connect to a printer if the connecting user
1660                    doesn't have print permission.  */
1661
1662                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1663                         close_printer_handle(p, handle);
1664                         ZERO_STRUCTP(r->out.handle);
1665                         return WERR_BADFID;
1666                 }
1667
1668                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1669
1670                 /* map an empty access mask to the minimum access mask */
1671                 if (r->in.access_mask == 0x0)
1672                         r->in.access_mask = PRINTER_ACCESS_USE;
1673
1674                 /*
1675                  * If we are not serving the printer driver for this printer,
1676                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1677                  * will keep NT clients happy  --jerry
1678                  */
1679
1680                 if (lp_use_client_driver(snum)
1681                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1682                 {
1683                         r->in.access_mask = PRINTER_ACCESS_USE;
1684                 }
1685
1686                 /* check smb.conf parameters and the the sec_desc */
1687
1688                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1689                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1690                         ZERO_STRUCTP(r->out.handle);
1691                         return WERR_ACCESS_DENIED;
1692                 }
1693
1694                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1695                                    p->server_info->ptok, snum) ||
1696                     !print_access_check(p->server_info, snum,
1697                                         r->in.access_mask)) {
1698                         DEBUG(3, ("access DENIED for printer open\n"));
1699                         close_printer_handle(p, handle);
1700                         ZERO_STRUCTP(r->out.handle);
1701                         return WERR_ACCESS_DENIED;
1702                 }
1703
1704                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1705                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1706                         close_printer_handle(p, handle);
1707                         ZERO_STRUCTP(r->out.handle);
1708                         return WERR_ACCESS_DENIED;
1709                 }
1710
1711                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1712                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1713                 else
1714                         r->in.access_mask = PRINTER_ACCESS_USE;
1715
1716                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1717                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1718
1719                 break;
1720
1721         default:
1722                 /* sanity check to prevent programmer error */
1723                 ZERO_STRUCTP(r->out.handle);
1724                 return WERR_BADFID;
1725         }
1726
1727         Printer->access_granted = r->in.access_mask;
1728
1729         /*
1730          * If the client sent a devmode in the OpenPrinter() call, then
1731          * save it here in case we get a job submission on this handle
1732          */
1733
1734          if ((Printer->printer_type != SPLHND_SERVER) &&
1735              r->in.devmode_ctr.devmode) {
1736                 convert_devicemode(Printer->sharename,
1737                                    r->in.devmode_ctr.devmode,
1738                                    &Printer->nt_devmode);
1739          }
1740
1741 #if 0   /* JERRY -- I'm doubtful this is really effective */
1742         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1743            optimization in Windows 2000 clients  --jerry */
1744
1745         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1746                 && (RA_WIN2K == get_remote_arch()) )
1747         {
1748                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1749                 sys_usleep( 500000 );
1750         }
1751 #endif
1752
1753         return WERR_OK;
1754 }
1755
1756 /****************************************************************************
1757 ****************************************************************************/
1758
1759 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1760                                               NT_PRINTER_INFO_LEVEL_2 *d)
1761 {
1762         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1763
1764         if (!r || !d) {
1765                 return false;
1766         }
1767
1768         d->attributes           = r->attributes;
1769         d->priority             = r->priority;
1770         d->default_priority     = r->defaultpriority;
1771         d->starttime            = r->starttime;
1772         d->untiltime            = r->untiltime;
1773         d->status               = r->status;
1774         d->cjobs                = r->cjobs;
1775
1776         fstrcpy(d->servername,  r->servername);
1777         fstrcpy(d->printername, r->printername);
1778         fstrcpy(d->sharename,   r->sharename);
1779         fstrcpy(d->portname,    r->portname);
1780         fstrcpy(d->drivername,  r->drivername);
1781         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1782         fstrcpy(d->location,    r->location);
1783         fstrcpy(d->sepfile,     r->sepfile);
1784         fstrcpy(d->printprocessor, r->printprocessor);
1785         fstrcpy(d->datatype,    r->datatype);
1786         fstrcpy(d->parameters,  r->parameters);
1787
1788         return true;
1789 }
1790
1791 /****************************************************************************
1792 ****************************************************************************/
1793
1794 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1795                                  NT_PRINTER_INFO_LEVEL *printer)
1796 {
1797         bool ret;
1798
1799         switch (info_ctr->level) {
1800         case 2:
1801                 /* allocate memory if needed.  Messy because
1802                    convert_printer_info is used to update an existing
1803                    printer or build a new one */
1804
1805                 if (!printer->info_2) {
1806                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1807                         if (!printer->info_2) {
1808                                 DEBUG(0,("convert_printer_info: "
1809                                         "talloc() failed!\n"));
1810                                 return false;
1811                         }
1812                 }
1813
1814                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1815                                                         printer->info_2);
1816                 printer->info_2->setuptime = time(NULL);
1817                 return ret;
1818         }
1819
1820         return false;
1821 }
1822
1823 /*******************************************************************
1824 ********************************************************************/
1825
1826 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1827 {
1828         int i;
1829
1830         if (!sarray) {
1831                 *farray = NULL;
1832                 return true;
1833         }
1834
1835         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1836         if (!*farray) {
1837                 return false;
1838         }
1839
1840         for (i=0; sarray[i] != NULL; i++) {
1841                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1842                 if (!*farray) {
1843                         return false;
1844                 }
1845                 fstrcpy((*farray)[i], sarray[i]);
1846         }
1847
1848         fstrcpy((*farray)[i], "");
1849
1850         return true;
1851 }
1852
1853 /*******************************************************************
1854 ********************************************************************/
1855
1856 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1857                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1858 {
1859         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1860
1861         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1862
1863         if (*p == NULL) {
1864                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1865                 if (*p == NULL) {
1866                         return false;
1867                 }
1868                 ZERO_STRUCTP(*p);
1869         }
1870
1871         d = *p;
1872
1873         d->cversion =                   r->version;
1874
1875         fstrcpy(d->name,                r->driver_name);
1876         fstrcpy(d->environment,         r->architecture);
1877         fstrcpy(d->driverpath,          r->driver_path);
1878         fstrcpy(d->datafile,            r->data_file);
1879         fstrcpy(d->configfile,          r->config_file);
1880         fstrcpy(d->helpfile,            r->help_file);
1881         fstrcpy(d->monitorname,         r->monitor_name);
1882         fstrcpy(d->defaultdatatype,     r->default_datatype);
1883
1884         DEBUGADD(8,( "version:         %d\n", d->cversion));
1885         DEBUGADD(8,( "name:            %s\n", d->name));
1886         DEBUGADD(8,( "environment:     %s\n", d->environment));
1887         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1888         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1889         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1890         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1891         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1892         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1893
1894         if (r->dependent_files) {
1895                 if (!string_array_to_fstring_array(r->dependent_files->string,
1896                                                    &d->dependentfiles)) {
1897                         SAFE_FREE(*p);
1898                         return false;
1899                 }
1900         }
1901
1902         return true;
1903 }
1904
1905 /*******************************************************************
1906 ********************************************************************/
1907
1908 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1909                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1910 {
1911         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1912
1913         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1914
1915         if (*p == NULL) {
1916                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1917                 if (*p == NULL) {
1918                         return false;
1919                 }
1920                 ZERO_STRUCTP(*p);
1921         }
1922
1923         d = *p;
1924
1925         d->version =                    r->version;
1926
1927         fstrcpy(d->name,                r->driver_name);
1928         fstrcpy(d->environment,         r->architecture);
1929         fstrcpy(d->driverpath,          r->driver_path);
1930         fstrcpy(d->datafile,            r->data_file);
1931         fstrcpy(d->configfile,          r->config_file);
1932         fstrcpy(d->helpfile,            r->help_file);
1933         fstrcpy(d->monitorname,         r->monitor_name);
1934         fstrcpy(d->defaultdatatype,     r->default_datatype);
1935
1936         DEBUGADD(8,( "version:         %d\n", d->version));
1937         DEBUGADD(8,( "name:            %s\n", d->name));
1938         DEBUGADD(8,( "environment:     %s\n", d->environment));
1939         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1940         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1941         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1942         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1943         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1944         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1945
1946         if (r->dependent_files) {
1947                 if (!string_array_to_fstring_array(r->dependent_files->string,
1948                                                    &d->dependentfiles)) {
1949                         goto error;
1950                 }
1951         }
1952
1953         if (r->previous_names) {
1954                 if (!string_array_to_fstring_array(r->previous_names->string,
1955                                                    &d->previousnames)) {
1956                         goto error;
1957                 }
1958         }
1959
1960         return true;
1961
1962  error:
1963         SAFE_FREE(*p);
1964         return false;
1965 }
1966
1967 /********************************************************************
1968  ********************************************************************/
1969
1970 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1971                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1972                                         uint32_t level)
1973 {
1974         switch (level) {
1975         case 3:
1976                 printer->info_3 = NULL;
1977                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1978                         return false;
1979                 }
1980                 break;
1981         case 6:
1982                 printer->info_6 = NULL;
1983                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1984                         return false;
1985                 }
1986                 break;
1987         default:
1988                 return false;
1989         }
1990
1991         return true;
1992 }
1993
1994 /********************************************************************
1995  * _spoolss_enddocprinter_internal.
1996  ********************************************************************/
1997
1998 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1999 {
2000         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2001         int snum;
2002
2003         if (!Printer) {
2004                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2005                 return WERR_BADFID;
2006         }
2007
2008         if (!get_printer_snum(p, handle, &snum, NULL))
2009                 return WERR_BADFID;
2010
2011         Printer->document_started=False;
2012         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2013         /* error codes unhandled so far ... */
2014
2015         return WERR_OK;
2016 }
2017
2018 /****************************************************************
2019  _spoolss_ClosePrinter
2020 ****************************************************************/
2021
2022 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2023                              struct spoolss_ClosePrinter *r)
2024 {
2025         POLICY_HND *handle = r->in.handle;
2026
2027         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2028
2029         if (Printer && Printer->document_started)
2030                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2031
2032         if (!close_printer_handle(p, handle))
2033                 return WERR_BADFID;
2034
2035         /* clear the returned printer handle.  Observed behavior
2036            from Win2k server.  Don't think this really matters.
2037            Previous code just copied the value of the closed
2038            handle.    --jerry */
2039
2040         ZERO_STRUCTP(r->out.handle);
2041
2042         return WERR_OK;
2043 }
2044
2045 /****************************************************************
2046  _spoolss_DeletePrinter
2047 ****************************************************************/
2048
2049 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2050                               struct spoolss_DeletePrinter *r)
2051 {
2052         POLICY_HND *handle = r->in.handle;
2053         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2054         WERROR result;
2055
2056         if (Printer && Printer->document_started)
2057                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2058
2059         result = delete_printer_handle(p, handle);
2060
2061         update_c_setprinter(False);
2062
2063         return result;
2064 }
2065
2066 /*******************************************************************
2067  * static function to lookup the version id corresponding to an
2068  * long architecture string
2069  ******************************************************************/
2070
2071 static int get_version_id (char * arch)
2072 {
2073         int i;
2074         struct table_node archi_table[]= {
2075
2076                 {"Windows 4.0",          "WIN40",       0 },
2077                 {"Windows NT x86",       "W32X86",      2 },
2078                 {"Windows NT R4000",     "W32MIPS",     2 },
2079                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2080                 {"Windows NT PowerPC",   "W32PPC",      2 },
2081                 {"Windows IA64",         "IA64",        3 },
2082                 {"Windows x64",          "x64",         3 },
2083                 {NULL,                   "",            -1 }
2084         };
2085
2086         for (i=0; archi_table[i].long_archi != NULL; i++)
2087         {
2088                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2089                         return (archi_table[i].version);
2090         }
2091
2092         return -1;
2093 }
2094
2095 /****************************************************************
2096  _spoolss_DeletePrinterDriver
2097 ****************************************************************/
2098
2099 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2100                                     struct spoolss_DeletePrinterDriver *r)
2101 {
2102         char *driver;
2103         char *arch;
2104         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2105         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2106         int                             version;
2107         WERROR                          status;
2108         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2109         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2110
2111         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2112            and not a printer admin, then fail */
2113
2114         if ( (p->server_info->utok.uid != 0)
2115                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2116                 && !token_contains_name_in_list(
2117                         uidtoname(p->server_info->utok.uid), NULL,
2118                         NULL, p->server_info->ptok,
2119                         lp_printer_admin(-1)) )
2120         {
2121                 return WERR_ACCESS_DENIED;
2122         }
2123
2124         driver = CONST_DISCARD(char *, r->in.driver);
2125         arch   = CONST_DISCARD(char *, r->in.architecture);
2126
2127         /* check that we have a valid driver name first */
2128
2129         if ((version=get_version_id(arch)) == -1)
2130                 return WERR_INVALID_ENVIRONMENT;
2131
2132         ZERO_STRUCT(info);
2133         ZERO_STRUCT(info_win2k);
2134
2135         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2136         {
2137                 /* try for Win2k driver if "Windows NT x86" */
2138
2139                 if ( version == 2 ) {
2140                         version = 3;
2141                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2142                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2143                                 goto done;
2144                         }
2145                 }
2146                 /* otherwise it was a failure */
2147                 else {
2148                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2149                         goto done;
2150                 }
2151
2152         }
2153
2154         if (printer_driver_in_use(info.info_3)) {
2155                 status = WERR_PRINTER_DRIVER_IN_USE;
2156                 goto done;
2157         }
2158
2159         if ( version == 2 )
2160         {
2161                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2162                 {
2163                         /* if we get to here, we now have 2 driver info structures to remove */
2164                         /* remove the Win2k driver first*/
2165
2166                         status_win2k = delete_printer_driver(
2167                                 p, info_win2k.info_3, 3, False );
2168                         free_a_printer_driver( info_win2k, 3 );
2169
2170                         /* this should not have failed---if it did, report to client */
2171                         if ( !W_ERROR_IS_OK(status_win2k) )
2172                         {
2173                                 status = status_win2k;
2174                                 goto done;
2175                         }
2176                 }
2177         }
2178
2179         status = delete_printer_driver(p, info.info_3, version, False);
2180
2181         /* if at least one of the deletes succeeded return OK */
2182
2183         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2184                 status = WERR_OK;
2185
2186 done:
2187         free_a_printer_driver( info, 3 );
2188
2189         return status;
2190 }
2191
2192 /****************************************************************
2193  _spoolss_DeletePrinterDriverEx
2194 ****************************************************************/
2195
2196 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2197                                       struct spoolss_DeletePrinterDriverEx *r)
2198 {
2199         char *driver;
2200         char *arch;
2201         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2202         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2203         int                             version;
2204         uint32_t                        flags = r->in.delete_flags;
2205         bool                            delete_files;
2206         WERROR                          status;
2207         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2208         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2209
2210         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2211            and not a printer admin, then fail */
2212
2213         if ( (p->server_info->utok.uid != 0)
2214                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2215                 && !token_contains_name_in_list(
2216                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2217                         p->server_info->ptok, lp_printer_admin(-1)) )
2218         {
2219                 return WERR_ACCESS_DENIED;
2220         }
2221
2222         driver = CONST_DISCARD(char *, r->in.driver);
2223         arch   = CONST_DISCARD(char *, r->in.architecture);
2224
2225         /* check that we have a valid driver name first */
2226         if ((version=get_version_id(arch)) == -1) {
2227                 /* this is what NT returns */
2228                 return WERR_INVALID_ENVIRONMENT;
2229         }
2230
2231         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2232                 version = r->in.version;
2233
2234         ZERO_STRUCT(info);
2235         ZERO_STRUCT(info_win2k);
2236
2237         status = get_a_printer_driver(&info, 3, driver, arch, version);
2238
2239         if ( !W_ERROR_IS_OK(status) )
2240         {
2241                 /*
2242                  * if the client asked for a specific version,
2243                  * or this is something other than Windows NT x86,
2244                  * then we've failed
2245                  */
2246
2247                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2248                         goto done;
2249
2250                 /* try for Win2k driver if "Windows NT x86" */
2251
2252                 version = 3;
2253                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2254                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2255                         goto done;
2256                 }
2257         }
2258
2259         if ( printer_driver_in_use(info.info_3) ) {
2260                 status = WERR_PRINTER_DRIVER_IN_USE;
2261                 goto done;
2262         }
2263
2264         /*
2265          * we have a couple of cases to consider.
2266          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2267          *     then the delete should fail if **any** files overlap with
2268          *     other drivers
2269          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2270          *     non-overlapping files
2271          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2272          *     is set, the do not delete any files
2273          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2274          */
2275
2276         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2277
2278         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2279
2280         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2281                 /* no idea of the correct error here */
2282                 status = WERR_ACCESS_DENIED;
2283                 goto done;
2284         }
2285
2286
2287         /* also check for W32X86/3 if necessary; maybe we already have? */
2288
2289         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2290                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2291                 {
2292
2293                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2294                                 /* no idea of the correct error here */
2295                                 free_a_printer_driver( info_win2k, 3 );
2296                                 status = WERR_ACCESS_DENIED;
2297                                 goto done;
2298                         }
2299
2300                         /* if we get to here, we now have 2 driver info structures to remove */
2301                         /* remove the Win2k driver first*/
2302
2303                         status_win2k = delete_printer_driver(
2304                                 p, info_win2k.info_3, 3, delete_files);
2305                         free_a_printer_driver( info_win2k, 3 );
2306
2307                         /* this should not have failed---if it did, report to client */
2308
2309                         if ( !W_ERROR_IS_OK(status_win2k) )
2310                                 goto done;
2311                 }
2312         }
2313
2314         status = delete_printer_driver(p, info.info_3, version, delete_files);
2315
2316         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2317                 status = WERR_OK;
2318 done:
2319         free_a_printer_driver( info, 3 );
2320
2321         return status;
2322 }
2323
2324
2325 /****************************************************************************
2326  Internal routine for removing printerdata
2327  ***************************************************************************/
2328
2329 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2330 {
2331         return delete_printer_data( printer->info_2, key, value );
2332 }
2333
2334 /****************************************************************************
2335  Internal routine for storing printerdata
2336  ***************************************************************************/
2337
2338 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2339                                   uint32 type, uint8 *data, int real_len  )
2340 {
2341         /* the registry objects enforce uniqueness based on value name */
2342
2343         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2344 }
2345
2346 /********************************************************************
2347  GetPrinterData on a printer server Handle.
2348 ********************************************************************/
2349
2350 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2351                                             const char *value,
2352                                             enum winreg_Type *type,
2353                                             union spoolss_PrinterData *data)
2354 {
2355         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2356
2357         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2358                 *type = REG_DWORD;
2359                 data->value = 0x00;
2360                 return WERR_OK;
2361         }
2362
2363         if (!StrCaseCmp(value, "BeepEnabled")) {
2364                 *type = REG_DWORD;
2365                 data->value = 0x00;
2366                 return WERR_OK;
2367         }
2368
2369         if (!StrCaseCmp(value, "EventLog")) {
2370                 *type = REG_DWORD;
2371                 /* formally was 0x1b */
2372                 data->value = 0x00;
2373                 return WERR_OK;
2374         }
2375
2376         if (!StrCaseCmp(value, "NetPopup")) {
2377                 *type = REG_DWORD;
2378                 data->value = 0x00;
2379                 return WERR_OK;
2380         }
2381
2382         if (!StrCaseCmp(value, "MajorVersion")) {
2383                 *type = REG_DWORD;
2384
2385                 /* Windows NT 4.0 seems to not allow uploading of drivers
2386                    to a server that reports 0x3 as the MajorVersion.
2387                    need to investigate more how Win2k gets around this .
2388                    -- jerry */
2389
2390                 if (RA_WINNT == get_remote_arch()) {
2391                         data->value = 0x02;
2392                 } else {
2393                         data->value = 0x03;
2394                 }
2395
2396                 return WERR_OK;
2397         }
2398
2399         if (!StrCaseCmp(value, "MinorVersion")) {
2400                 *type = REG_DWORD;
2401                 data->value = 0x00;
2402                 return WERR_OK;
2403         }
2404
2405         /* REG_BINARY
2406          *  uint32 size          = 0x114
2407          *  uint32 major         = 5
2408          *  uint32 minor         = [0|1]
2409          *  uint32 build         = [2195|2600]
2410          *  extra unicode string = e.g. "Service Pack 3"
2411          */
2412         if (!StrCaseCmp(value, "OSVersion")) {
2413                 DATA_BLOB blob;
2414                 enum ndr_err_code ndr_err;
2415                 struct spoolss_OSVersion os;
2416
2417                 os.major                = 5;    /* Windows 2000 == 5.0 */
2418                 os.minor                = 0;
2419                 os.build                = 2195; /* build */
2420                 os.extra_string         = "";   /* leave extra string empty */
2421
2422                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2423                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2424                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2425                         return WERR_GENERAL_FAILURE;
2426                 }
2427
2428                 *type = REG_BINARY;
2429                 data->binary = blob;
2430
2431                 return WERR_OK;
2432         }
2433
2434
2435         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2436                 *type = REG_SZ;
2437
2438                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2439                 W_ERROR_HAVE_NO_MEMORY(data->string);
2440
2441                 return WERR_OK;
2442         }
2443
2444         if (!StrCaseCmp(value, "Architecture")) {
2445                 *type = REG_SZ;
2446
2447                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2448                 W_ERROR_HAVE_NO_MEMORY(data->string);
2449
2450                 return WERR_OK;
2451         }
2452
2453         if (!StrCaseCmp(value, "DsPresent")) {
2454                 *type = REG_DWORD;
2455
2456                 /* only show the publish check box if we are a
2457                    member of a AD domain */
2458
2459                 if (lp_security() == SEC_ADS) {
2460                         data->value = 0x01;
2461                 } else {
2462                         data->value = 0x00;
2463                 }
2464                 return WERR_OK;
2465         }
2466
2467         if (!StrCaseCmp(value, "DNSMachineName")) {
2468                 const char *hostname = get_mydnsfullname();
2469
2470                 if (!hostname) {
2471                         return WERR_BADFILE;
2472                 }
2473
2474                 *type = REG_SZ;
2475                 data->string = talloc_strdup(mem_ctx, hostname);
2476                 W_ERROR_HAVE_NO_MEMORY(data->string);
2477
2478                 return WERR_OK;
2479         }
2480
2481         return WERR_BADFILE;
2482 }
2483
2484 /****************************************************************
2485  _spoolss_GetPrinterData
2486 ****************************************************************/
2487
2488 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2489                                struct spoolss_GetPrinterData *r)
2490 {
2491         WERROR result;
2492         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2493         NT_PRINTER_INFO_LEVEL *printer = NULL;
2494         int snum = 0;
2495
2496         /*
2497          * Reminder: when it's a string, the length is in BYTES
2498          * even if UNICODE is negociated.
2499          *
2500          * JFM, 4/19/1999
2501          */
2502
2503         /* in case of problem, return some default values */
2504
2505         *r->out.needed  = 0;
2506         *r->out.type    = 0;
2507
2508         DEBUG(4,("_spoolss_GetPrinterData\n"));
2509
2510         if (!Printer) {
2511                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2512                         OUR_HANDLE(r->in.handle)));
2513                 result = WERR_BADFID;
2514                 goto done;
2515         }
2516
2517         if (Printer->printer_type == SPLHND_SERVER) {
2518                 result = getprinterdata_printer_server(p->mem_ctx,
2519                                                        r->in.value_name,
2520                                                        r->out.type,
2521                                                        r->out.data);
2522         } else {
2523                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2524                         result = WERR_BADFID;
2525                         goto done;
2526                 }
2527
2528                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2529                 if (!W_ERROR_IS_OK(result)) {
2530                         goto done;
2531                 }
2532
2533                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2534
2535                 if (strequal(r->in.value_name, "ChangeId")) {
2536                         *r->out.type = REG_DWORD;
2537                         r->out.data->value = printer->info_2->changeid;
2538                         result = WERR_OK;
2539                 } else {
2540                         REGISTRY_VALUE *v;
2541                         DATA_BLOB blob;
2542
2543                         v = get_printer_data(printer->info_2,
2544                                              SPOOL_PRINTERDATA_KEY,
2545                                              r->in.value_name);
2546                         if (!v) {
2547                                 result = WERR_BADFILE;
2548                                 goto done;
2549                         }
2550
2551                         *r->out.type = v->type;
2552
2553                         blob = data_blob_const(v->data_p, v->size);
2554
2555                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2556                                                           r->out.data,
2557                                                           *r->out.type);
2558                 }
2559         }
2560
2561  done:
2562         /* cleanup & exit */
2563
2564         if (printer) {
2565                 free_a_printer(&printer, 2);
2566         }
2567
2568         if (!W_ERROR_IS_OK(result)) {
2569                 return result;
2570         }
2571
2572         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2573         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2574         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2575
2576         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2577 }
2578
2579 /*********************************************************
2580  Connect to the client machine.
2581 **********************************************************/
2582
2583 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2584                         struct sockaddr_storage *client_ss, const char *remote_machine)
2585 {
2586         NTSTATUS ret;
2587         struct cli_state *the_cli;
2588         struct sockaddr_storage rm_addr;
2589
2590         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2591                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2592                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2593                         return False;
2594                 }
2595
2596                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2597                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2598                         return False;
2599                 }
2600         } else {
2601                 char addr[INET6_ADDRSTRLEN];
2602                 rm_addr = *client_ss;
2603                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2604                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2605                         addr));
2606         }
2607
2608         /* setup the connection */
2609
2610         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2611                 &rm_addr, 0, "IPC$", "IPC",
2612                 "", /* username */
2613                 "", /* domain */
2614                 "", /* password */
2615                 0, lp_client_signing(), NULL );
2616
2617         if ( !NT_STATUS_IS_OK( ret ) ) {
2618                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2619                         remote_machine ));
2620                 return False;
2621         }
2622
2623         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2624                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2625                 cli_shutdown(the_cli);
2626                 return False;
2627         }
2628
2629         /*
2630          * Ok - we have an anonymous connection to the IPC$ share.
2631          * Now start the NT Domain stuff :-).
2632          */
2633
2634         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2635         if (!NT_STATUS_IS_OK(ret)) {
2636                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2637                         remote_machine, nt_errstr(ret)));
2638                 cli_shutdown(the_cli);
2639                 return False;
2640         }
2641
2642         return True;
2643 }
2644
2645 /***************************************************************************
2646  Connect to the client.
2647 ****************************************************************************/
2648
2649 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2650                                         uint32 localprinter, uint32 type,
2651                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2652 {
2653         WERROR result;
2654         NTSTATUS status;
2655
2656         /*
2657          * If it's the first connection, contact the client
2658          * and connect to the IPC$ share anonymously
2659          */
2660         if (smb_connections==0) {
2661                 fstring unix_printer;
2662
2663                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2664
2665                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2666                         return False;
2667
2668                 messaging_register(smbd_messaging_context(), NULL,
2669                                    MSG_PRINTER_NOTIFY2,
2670                                    receive_notify2_message_list);
2671                 /* Tell the connections db we're now interested in printer
2672                  * notify messages. */
2673                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2674         }
2675
2676         /*
2677          * Tell the specific printing tdb we want messages for this printer
2678          * by registering our PID.
2679          */
2680
2681         if (!print_notify_register_pid(snum))
2682                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2683
2684         smb_connections++;
2685
2686         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2687                                                  printer,
2688                                                  localprinter,
2689                                                  type,
2690                                                  0,
2691                                                  NULL,
2692                                                  handle,
2693                                                  &result);
2694         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2695                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2696                         win_errstr(result)));
2697
2698         return (W_ERROR_IS_OK(result));
2699 }
2700
2701 /****************************************************************
2702  ****************************************************************/
2703
2704 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2705                                                              const struct spoolss_NotifyOption *r)
2706 {
2707         struct spoolss_NotifyOption *option;
2708         uint32_t i,k;
2709
2710         if (!r) {
2711                 return NULL;
2712         }
2713
2714         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2715         if (!option) {
2716                 return NULL;
2717         }
2718
2719         *option = *r;
2720
2721         if (!option->count) {
2722                 return option;
2723         }
2724
2725         option->types = talloc_zero_array(option,
2726                 struct spoolss_NotifyOptionType, option->count);
2727         if (!option->types) {
2728                 talloc_free(option);
2729                 return NULL;
2730         }
2731
2732         for (i=0; i < option->count; i++) {
2733                 option->types[i] = r->types[i];
2734
2735                 if (option->types[i].count) {
2736                         option->types[i].fields = talloc_zero_array(option,
2737                                 enum spoolss_Field, option->types[i].count);
2738                         if (!option->types[i].fields) {
2739                                 talloc_free(option);
2740                                 return NULL;
2741                         }
2742                         for (k=0; k<option->types[i].count; k++) {
2743                                 option->types[i].fields[k] =
2744                                         r->types[i].fields[k];
2745                         }
2746                 }
2747         }
2748
2749         return option;
2750 }
2751
2752 /****************************************************************
2753  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2754  *
2755  * before replying OK: status=0 a rpc call is made to the workstation
2756  * asking ReplyOpenPrinter
2757  *
2758  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2759  * called from api_spoolss_rffpcnex
2760 ****************************************************************/
2761
2762 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2763                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2764 {
2765         POLICY_HND *handle = r->in.handle;
2766         int snum = -1;
2767         struct spoolss_NotifyOption *option = r->in.notify_options;
2768         struct sockaddr_storage client_ss;
2769
2770         /* store the notify value in the printer struct */
2771
2772         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2773
2774         if (!Printer) {
2775                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2776                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2777                 return WERR_BADFID;
2778         }
2779
2780         Printer->notify.flags           = r->in.flags;
2781         Printer->notify.options         = r->in.options;
2782         Printer->notify.printerlocal    = r->in.printer_local;
2783
2784         TALLOC_FREE(Printer->notify.option);
2785         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2786
2787         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2788
2789         /* Connect to the client machine and send a ReplyOpenPrinter */
2790
2791         if ( Printer->printer_type == SPLHND_SERVER)
2792                 snum = -1;
2793         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2794                         !get_printer_snum(p, handle, &snum, NULL) )
2795                 return WERR_BADFID;
2796
2797         if (!interpret_string_addr(&client_ss, p->client_address,
2798                                    AI_NUMERICHOST)) {
2799                 return WERR_SERVER_UNAVAILABLE;
2800         }
2801
2802         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2803                                         Printer->notify.printerlocal, 1,
2804                                         &Printer->notify.client_hnd, &client_ss))
2805                 return WERR_SERVER_UNAVAILABLE;
2806
2807         Printer->notify.client_connected=True;
2808
2809         return WERR_OK;
2810 }
2811
2812 /*******************************************************************
2813  * fill a notify_info_data with the servername
2814  ********************************************************************/
2815
2816 void spoolss_notify_server_name(int snum,
2817                                        struct spoolss_Notify *data,
2818                                        print_queue_struct *queue,
2819                                        NT_PRINTER_INFO_LEVEL *printer,
2820                                        TALLOC_CTX *mem_ctx)
2821 {
2822         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2823 }
2824
2825 /*******************************************************************
2826  * fill a notify_info_data with the printername (not including the servername).
2827  ********************************************************************/
2828
2829 void spoolss_notify_printer_name(int snum,
2830                                         struct spoolss_Notify *data,
2831                                         print_queue_struct *queue,
2832                                         NT_PRINTER_INFO_LEVEL *printer,
2833                                         TALLOC_CTX *mem_ctx)
2834 {
2835         /* the notify name should not contain the \\server\ part */
2836         char *p = strrchr(printer->info_2->printername, '\\');
2837
2838         if (!p) {
2839                 p = printer->info_2->printername;
2840         } else {
2841                 p++;
2842         }
2843
2844         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2845 }
2846
2847 /*******************************************************************
2848  * fill a notify_info_data with the servicename
2849  ********************************************************************/
2850
2851 void spoolss_notify_share_name(int snum,
2852                                       struct spoolss_Notify *data,
2853                                       print_queue_struct *queue,
2854                                       NT_PRINTER_INFO_LEVEL *printer,
2855                                       TALLOC_CTX *mem_ctx)
2856 {
2857         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2858 }
2859
2860 /*******************************************************************
2861  * fill a notify_info_data with the port name
2862  ********************************************************************/
2863
2864 void spoolss_notify_port_name(int snum,
2865                                      struct spoolss_Notify *data,
2866                                      print_queue_struct *queue,
2867                                      NT_PRINTER_INFO_LEVEL *printer,
2868                                      TALLOC_CTX *mem_ctx)
2869 {
2870         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2871 }
2872
2873 /*******************************************************************
2874  * fill a notify_info_data with the printername
2875  * but it doesn't exist, have to see what to do
2876  ********************************************************************/
2877
2878 void spoolss_notify_driver_name(int snum,
2879                                        struct spoolss_Notify *data,
2880                                        print_queue_struct *queue,
2881                                        NT_PRINTER_INFO_LEVEL *printer,
2882                                        TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with the comment
2889  ********************************************************************/
2890
2891 void spoolss_notify_comment(int snum,
2892                                    struct spoolss_Notify *data,
2893                                    print_queue_struct *queue,
2894                                    NT_PRINTER_INFO_LEVEL *printer,
2895                                    TALLOC_CTX *mem_ctx)
2896 {
2897         char *p;
2898
2899         if (*printer->info_2->comment == '\0') {
2900                 p = lp_comment(snum);
2901         } else {
2902                 p = printer->info_2->comment;
2903         }
2904
2905         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2906 }
2907
2908 /*******************************************************************
2909  * fill a notify_info_data with the comment
2910  * location = "Room 1, floor 2, building 3"
2911  ********************************************************************/
2912
2913 void spoolss_notify_location(int snum,
2914                                     struct spoolss_Notify *data,
2915                                     print_queue_struct *queue,
2916                                     NT_PRINTER_INFO_LEVEL *printer,
2917                                     TALLOC_CTX *mem_ctx)
2918 {
2919         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2920 }
2921
2922 /*******************************************************************
2923  * fill a notify_info_data with the device mode
2924  * jfm:xxxx don't to it for know but that's a real problem !!!
2925  ********************************************************************/
2926
2927 static void spoolss_notify_devmode(int snum,
2928                                    struct spoolss_Notify *data,
2929                                    print_queue_struct *queue,
2930                                    NT_PRINTER_INFO_LEVEL *printer,
2931                                    TALLOC_CTX *mem_ctx)
2932 {
2933         /* for a dummy implementation we have to zero the fields */
2934         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2935 }
2936
2937 /*******************************************************************
2938  * fill a notify_info_data with the separator file name
2939  ********************************************************************/
2940
2941 void spoolss_notify_sepfile(int snum,
2942                                    struct spoolss_Notify *data,
2943                                    print_queue_struct *queue,
2944                                    NT_PRINTER_INFO_LEVEL *printer,
2945                                    TALLOC_CTX *mem_ctx)
2946 {
2947         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2948 }
2949
2950 /*******************************************************************
2951  * fill a notify_info_data with the print processor
2952  * jfm:xxxx return always winprint to indicate we don't do anything to it
2953  ********************************************************************/
2954
2955 void spoolss_notify_print_processor(int snum,
2956                                            struct spoolss_Notify *data,
2957                                            print_queue_struct *queue,
2958                                            NT_PRINTER_INFO_LEVEL *printer,
2959                                            TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with the print processor options
2966  * jfm:xxxx send an empty string
2967  ********************************************************************/
2968
2969 void spoolss_notify_parameters(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, printer->info_2->parameters);
2976 }
2977
2978 /*******************************************************************
2979  * fill a notify_info_data with the data type
2980  * jfm:xxxx always send RAW as data type
2981  ********************************************************************/
2982
2983 void spoolss_notify_datatype(int snum,
2984                                     struct spoolss_Notify *data,
2985                                     print_queue_struct *queue,
2986                                     NT_PRINTER_INFO_LEVEL *printer,
2987                                     TALLOC_CTX *mem_ctx)
2988 {
2989         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the security descriptor
2994  * jfm:xxxx send an null pointer to say no security desc
2995  * have to implement security before !
2996  ********************************************************************/
2997
2998 static void spoolss_notify_security_desc(int snum,
2999                                          struct spoolss_Notify *data,
3000                                          print_queue_struct *queue,
3001                                          NT_PRINTER_INFO_LEVEL *printer,
3002                                          TALLOC_CTX *mem_ctx)
3003 {
3004         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3005                                           printer->info_2->secdesc_buf->sd_size,
3006                                           printer->info_2->secdesc_buf->sd);
3007 }
3008
3009 /*******************************************************************
3010  * fill a notify_info_data with the attributes
3011  * jfm:xxxx a samba printer is always shared
3012  ********************************************************************/
3013
3014 void spoolss_notify_attributes(int snum,
3015                                       struct spoolss_Notify *data,
3016                                       print_queue_struct *queue,
3017                                       NT_PRINTER_INFO_LEVEL *printer,
3018                                       TALLOC_CTX *mem_ctx)
3019 {
3020         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3021 }
3022
3023 /*******************************************************************
3024  * fill a notify_info_data with the priority
3025  ********************************************************************/
3026
3027 static void spoolss_notify_priority(int snum,
3028                                     struct spoolss_Notify *data,
3029                                     print_queue_struct *queue,
3030                                     NT_PRINTER_INFO_LEVEL *printer,
3031                                     TALLOC_CTX *mem_ctx)
3032 {
3033         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the default priority
3038  ********************************************************************/
3039
3040 static void spoolss_notify_default_priority(int snum,
3041                                             struct spoolss_Notify *data,
3042                                             print_queue_struct *queue,
3043                                             NT_PRINTER_INFO_LEVEL *printer,
3044                                             TALLOC_CTX *mem_ctx)
3045 {
3046         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3047 }
3048
3049 /*******************************************************************
3050  * fill a notify_info_data with the start time
3051  ********************************************************************/
3052
3053 static void spoolss_notify_start_time(int snum,
3054                                       struct spoolss_Notify *data,
3055                                       print_queue_struct *queue,
3056                                       NT_PRINTER_INFO_LEVEL *printer,
3057                                       TALLOC_CTX *mem_ctx)
3058 {
3059         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with the until time
3064  ********************************************************************/
3065
3066 static void spoolss_notify_until_time(int snum,
3067                                       struct spoolss_Notify *data,
3068                                       print_queue_struct *queue,
3069                                       NT_PRINTER_INFO_LEVEL *printer,
3070                                       TALLOC_CTX *mem_ctx)
3071 {
3072         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3073 }
3074
3075 /*******************************************************************
3076  * fill a notify_info_data with the status
3077  ********************************************************************/
3078
3079 static void spoolss_notify_status(int snum,
3080                                   struct spoolss_Notify *data,
3081                                   print_queue_struct *queue,
3082                                   NT_PRINTER_INFO_LEVEL *printer,
3083                                   TALLOC_CTX *mem_ctx)
3084 {
3085         print_status_struct status;
3086
3087         print_queue_length(snum, &status);
3088         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with the number of jobs queued
3093  ********************************************************************/
3094
3095 void spoolss_notify_cjobs(int snum,
3096                                  struct spoolss_Notify *data,
3097                                  print_queue_struct *queue,
3098                                  NT_PRINTER_INFO_LEVEL *printer,
3099                                  TALLOC_CTX *mem_ctx)
3100 {
3101         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with the average ppm
3106  ********************************************************************/
3107
3108 static void spoolss_notify_average_ppm(int snum,
3109                                        struct spoolss_Notify *data,
3110                                        print_queue_struct *queue,
3111                                        NT_PRINTER_INFO_LEVEL *printer,
3112                                        TALLOC_CTX *mem_ctx)
3113 {
3114         /* always respond 8 pages per minutes */
3115         /* a little hard ! */
3116         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3117 }
3118
3119 /*******************************************************************
3120  * fill a notify_info_data with username
3121  ********************************************************************/
3122
3123 static void spoolss_notify_username(int snum,
3124                                     struct spoolss_Notify *data,
3125                                     print_queue_struct *queue,
3126                                     NT_PRINTER_INFO_LEVEL *printer,
3127                                     TALLOC_CTX *mem_ctx)
3128 {
3129         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with job status
3134  ********************************************************************/
3135
3136 static void spoolss_notify_job_status(int snum,
3137                                       struct spoolss_Notify *data,
3138                                       print_queue_struct *queue,
3139                                       NT_PRINTER_INFO_LEVEL *printer,
3140                                       TALLOC_CTX *mem_ctx)
3141 {
3142         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3143 }
3144
3145 /*******************************************************************
3146  * fill a notify_info_data with job name
3147  ********************************************************************/
3148
3149 static void spoolss_notify_job_name(int snum,
3150                                     struct spoolss_Notify *data,
3151                                     print_queue_struct *queue,
3152                                     NT_PRINTER_INFO_LEVEL *printer,
3153                                     TALLOC_CTX *mem_ctx)
3154 {
3155         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3156 }
3157
3158 /*******************************************************************
3159  * fill a notify_info_data with job status
3160  ********************************************************************/
3161
3162 static void spoolss_notify_job_status_string(int snum,
3163                                              struct spoolss_Notify *data,
3164                                              print_queue_struct *queue,
3165                                              NT_PRINTER_INFO_LEVEL *printer,
3166                                              TALLOC_CTX *mem_ctx)
3167 {
3168         /*
3169          * Now we're returning job status codes we just return a "" here. JRA.
3170          */
3171
3172         const char *p = "";
3173
3174 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3175         p = "unknown";
3176
3177         switch (queue->status) {
3178         case LPQ_QUEUED:
3179                 p = "Queued";
3180                 break;
3181         case LPQ_PAUSED:
3182                 p = "";    /* NT provides the paused string */
3183                 break;
3184         case LPQ_SPOOLING:
3185                 p = "Spooling";
3186                 break;
3187         case LPQ_PRINTING:
3188                 p = "Printing";
3189                 break;
3190         }
3191 #endif /* NO LONGER NEEDED. */
3192
3193         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3194 }
3195
3196 /*******************************************************************
3197  * fill a notify_info_data with job time
3198  ********************************************************************/
3199
3200 static void spoolss_notify_job_time(int snum,
3201                                     struct spoolss_Notify *data,
3202                                     print_queue_struct *queue,
3203                                     NT_PRINTER_INFO_LEVEL *printer,
3204                                     TALLOC_CTX *mem_ctx)
3205 {
3206         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3207 }
3208
3209 /*******************************************************************
3210  * fill a notify_info_data with job size
3211  ********************************************************************/
3212
3213 static void spoolss_notify_job_size(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, queue->size);
3220 }
3221
3222 /*******************************************************************
3223  * fill a notify_info_data with page info
3224  ********************************************************************/
3225 static void spoolss_notify_total_pages(int snum,
3226                                 struct spoolss_Notify *data,
3227                                 print_queue_struct *queue,
3228                                 NT_PRINTER_INFO_LEVEL *printer,
3229                                 TALLOC_CTX *mem_ctx)
3230 {
3231         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3232 }
3233
3234 /*******************************************************************
3235  * fill a notify_info_data with pages printed info.
3236  ********************************************************************/
3237 static void spoolss_notify_pages_printed(int snum,
3238                                 struct spoolss_Notify *data,
3239                                 print_queue_struct *queue,
3240                                 NT_PRINTER_INFO_LEVEL *printer,
3241                                 TALLOC_CTX *mem_ctx)
3242 {
3243         /* Add code when back-end tracks this */
3244         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3245 }
3246
3247 /*******************************************************************
3248  Fill a notify_info_data with job position.
3249  ********************************************************************/
3250
3251 static void spoolss_notify_job_position(int snum,
3252                                         struct spoolss_Notify *data,
3253                                         print_queue_struct *queue,
3254                                         NT_PRINTER_INFO_LEVEL *printer,
3255                                         TALLOC_CTX *mem_ctx)
3256 {
3257         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3258 }
3259
3260 /*******************************************************************
3261  Fill a notify_info_data with submitted time.
3262  ********************************************************************/
3263
3264 static void spoolss_notify_submitted_time(int snum,
3265                                           struct spoolss_Notify *data,
3266                                           print_queue_struct *queue,
3267                                           NT_PRINTER_INFO_LEVEL *printer,
3268                                           TALLOC_CTX *mem_ctx)
3269 {
3270         data->data.string.string = NULL;
3271         data->data.string.size = 0;
3272
3273         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3274                                &data->data.string.string,
3275                                &data->data.string.size);
3276
3277 }
3278
3279 struct s_notify_info_data_table
3280 {
3281         enum spoolss_NotifyType type;
3282         enum spoolss_Field field;
3283         const char *name;
3284         enum spoolss_NotifyTable variable_type;
3285         void (*fn) (int snum, struct spoolss_Notify *data,
3286                     print_queue_struct *queue,
3287                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3288 };
3289
3290 /* A table describing the various print notification constants and
3291    whether the notification data is a pointer to a variable sized
3292    buffer, a one value uint32 or a two value uint32. */
3293
3294 static const struct s_notify_info_data_table notify_info_data_table[] =
3295 {
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3332 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3333 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3334 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3335 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3336 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3337 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3338 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3339 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3340 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3341 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3342 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3343 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3344 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3345 };
3346
3347 /*******************************************************************
3348  Return the variable_type of info_data structure.
3349 ********************************************************************/
3350
3351 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3352                                                   enum spoolss_Field field)
3353 {
3354         int i=0;
3355
3356         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3357                 if ( (notify_info_data_table[i].type == type) &&
3358                      (notify_info_data_table[i].field == field) ) {
3359                         return notify_info_data_table[i].variable_type;
3360                 }
3361         }
3362
3363         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3364
3365         return 0;
3366 }
3367
3368 /****************************************************************************
3369 ****************************************************************************/
3370
3371 static bool search_notify(enum spoolss_NotifyType type,
3372                           enum spoolss_Field field,
3373                           int *value)
3374 {
3375         int i;
3376
3377         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3378                 if (notify_info_data_table[i].type == type &&
3379                     notify_info_data_table[i].field == field &&
3380                     notify_info_data_table[i].fn != NULL) {
3381                         *value = i;
3382                         return True;
3383                 }
3384         }
3385
3386         return False;
3387 }
3388
3389 /****************************************************************************
3390 ****************************************************************************/
3391
3392 void construct_info_data(struct spoolss_Notify *info_data,
3393                          enum spoolss_NotifyType type,
3394                          enum spoolss_Field field,
3395                          int id)
3396 {
3397         info_data->type                 = type;
3398         info_data->field                = field;
3399         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3400         info_data->job_id               = id;
3401 }
3402
3403 /*******************************************************************
3404  *
3405  * fill a notify_info struct with info asked
3406  *
3407  ********************************************************************/
3408
3409 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3410                                           struct spoolss_NotifyInfo *info,
3411                                           int snum,
3412                                           const struct spoolss_NotifyOptionType *option_type,
3413                                           uint32_t id,
3414                                           TALLOC_CTX *mem_ctx)
3415 {
3416         int field_num,j;
3417         enum spoolss_NotifyType type;
3418         enum spoolss_Field field;
3419
3420         struct spoolss_Notify *current_data;
3421         NT_PRINTER_INFO_LEVEL *printer = NULL;
3422         print_queue_struct *queue=NULL;
3423
3424         type = option_type->type;
3425
3426         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3427                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3428                 option_type->count, lp_servicename(snum)));
3429
3430         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3431                 return False;
3432
3433         for(field_num=0; field_num < option_type->count; field_num++) {
3434                 field = option_type->fields[field_num];
3435
3436                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3437
3438                 if (!search_notify(type, field, &j) )
3439                         continue;
3440
3441                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3442                                                       struct spoolss_Notify,
3443                                                       info->count + 1);
3444                 if (info->notifies == NULL) {
3445                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3446                         free_a_printer(&printer, 2);
3447                         return False;
3448                 }
3449
3450                 current_data = &info->notifies[info->count];
3451
3452                 construct_info_data(current_data, type, field, id);
3453
3454                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3455                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3456
3457                 notify_info_data_table[j].fn(snum, current_data, queue,
3458                                              printer, mem_ctx);
3459
3460                 info->count++;
3461         }
3462
3463         free_a_printer(&printer, 2);
3464         return True;
3465 }
3466
3467 /*******************************************************************
3468  *
3469  * fill a notify_info struct with info asked
3470  *
3471  ********************************************************************/
3472
3473 static bool construct_notify_jobs_info(print_queue_struct *queue,
3474                                        struct spoolss_NotifyInfo *info,
3475                                        NT_PRINTER_INFO_LEVEL *printer,
3476                                        int snum,
3477                                        const struct spoolss_NotifyOptionType *option_type,
3478                                        uint32_t id,
3479                                        TALLOC_CTX *mem_ctx)
3480 {
3481         int field_num,j;
3482         enum spoolss_NotifyType type;
3483         enum spoolss_Field field;
3484         struct spoolss_Notify *current_data;
3485
3486         DEBUG(4,("construct_notify_jobs_info\n"));
3487
3488         type = option_type->type;
3489
3490         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3491                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3492                 option_type->count));
3493
3494         for(field_num=0; field_num<option_type->count; field_num++) {
3495                 field = option_type->fields[field_num];
3496
3497                 if (!search_notify(type, field, &j) )
3498                         continue;
3499
3500                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3501                                                       struct spoolss_Notify,
3502                                                       info->count + 1);
3503                 if (info->notifies == NULL) {
3504                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3505                         return False;
3506                 }
3507
3508                 current_data=&(info->notifies[info->count]);
3509
3510                 construct_info_data(current_data, type, field, id);
3511                 notify_info_data_table[j].fn(snum, current_data, queue,
3512                                              printer, mem_ctx);
3513                 info->count++;
3514         }
3515
3516         return True;
3517 }
3518
3519 /*
3520  * JFM: The enumeration is not that simple, it's even non obvious.
3521  *
3522  * let's take an example: I want to monitor the PRINTER SERVER for
3523  * the printer's name and the number of jobs currently queued.
3524  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3525  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3526  *
3527  * I have 3 printers on the back of my server.
3528  *
3529  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3530  * structures.
3531  *   Number     Data                    Id
3532  *      1       printer 1 name          1
3533  *      2       printer 1 cjob          1
3534  *      3       printer 2 name          2
3535  *      4       printer 2 cjob          2
3536  *      5       printer 3 name          3
3537  *      6       printer 3 name          3
3538  *
3539  * that's the print server case, the printer case is even worse.
3540  */
3541
3542 /*******************************************************************
3543  *
3544  * enumerate all printers on the printserver
3545  * fill a notify_info struct with info asked
3546  *
3547  ********************************************************************/
3548
3549 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3550                                       struct spoolss_NotifyInfo *info,
3551                                       TALLOC_CTX *mem_ctx)
3552 {
3553         int snum;
3554         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3555         int n_services=lp_numservices();
3556         int i;
3557         struct spoolss_NotifyOption *option;
3558         struct spoolss_NotifyOptionType option_type;
3559
3560         DEBUG(4,("printserver_notify_info\n"));
3561
3562         if (!Printer)
3563                 return WERR_BADFID;
3564
3565         option = Printer->notify.option;
3566
3567         info->version   = 2;
3568         info->notifies  = NULL;
3569         info->count     = 0;
3570
3571         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3572            sending a ffpcn() request first */
3573
3574         if ( !option )
3575                 return WERR_BADFID;
3576
3577         for (i=0; i<option->count; i++) {
3578                 option_type = option->types[i];
3579
3580                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3581                         continue;
3582
3583                 for (snum=0; snum<n_services; snum++)
3584                 {
3585                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3586                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3587                 }
3588         }
3589
3590 #if 0
3591         /*
3592          * Debugging information, don't delete.
3593          */
3594
3595         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3596         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3597         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3598
3599         for (i=0; i<info->count; i++) {
3600                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3601                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3602                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3603         }
3604 #endif
3605
3606         return WERR_OK;
3607 }
3608
3609 /*******************************************************************
3610  *
3611  * fill a notify_info struct with info asked
3612  *
3613  ********************************************************************/
3614
3615 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3616                                   TALLOC_CTX *mem_ctx)
3617 {
3618         int snum;
3619         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3620         int i;
3621         uint32 id;
3622         struct spoolss_NotifyOption *option;
3623         struct spoolss_NotifyOptionType option_type;
3624         int count,j;
3625         print_queue_struct *queue=NULL;
3626         print_status_struct status;
3627
3628         DEBUG(4,("printer_notify_info\n"));
3629
3630         if (!Printer)
3631                 return WERR_BADFID;
3632
3633         option = Printer->notify.option;
3634         id = 0x0;
3635
3636         info->version   = 2;
3637         info->notifies  = NULL;
3638         info->count     = 0;
3639
3640         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3641            sending a ffpcn() request first */
3642
3643         if ( !option )
3644                 return WERR_BADFID;
3645
3646         get_printer_snum(p, hnd, &snum, NULL);
3647
3648         for (i=0; i<option->count; i++) {
3649                 option_type = option->types[i];
3650
3651                 switch (option_type.type) {
3652                 case PRINTER_NOTIFY_TYPE:
3653                         if(construct_notify_printer_info(Printer, info, snum,
3654                                                          &option_type, id,
3655                                                          mem_ctx))
3656                                 id--;
3657                         break;
3658
3659                 case JOB_NOTIFY_TYPE: {
3660                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3661
3662                         count = print_queue_status(snum, &queue, &status);
3663
3664                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3665                                 goto done;
3666
3667                         for (j=0; j<count; j++) {
3668                                 construct_notify_jobs_info(&queue[j], info,
3669                                                            printer, snum,
3670                                                            &option_type,
3671                                                            queue[j].job,
3672                                                            mem_ctx);
3673                         }
3674
3675                         free_a_printer(&printer, 2);
3676
3677                 done:
3678                         SAFE_FREE(queue);
3679                         break;
3680                 }
3681                 }
3682         }
3683
3684         /*
3685          * Debugging information, don't delete.
3686          */
3687         /*
3688         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3689         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3690         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3691
3692         for (i=0; i<info->count; i++) {
3693                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3694                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3695                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3696         }
3697         */
3698         return WERR_OK;
3699 }
3700
3701 /****************************************************************
3702  _spoolss_RouterRefreshPrinterChangeNotify
3703 ****************************************************************/
3704
3705 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3706                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3707 {
3708         POLICY_HND *handle = r->in.handle;
3709         struct spoolss_NotifyInfo *info;
3710
3711         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3712         WERROR result = WERR_BADFID;
3713
3714         /* we always have a spoolss_NotifyInfo struct */
3715         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3716         if (!info) {
3717                 result = WERR_NOMEM;
3718                 goto done;
3719         }
3720
3721         *r->out.info = info;
3722
3723         if (!Printer) {
3724                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3725                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3726                 goto done;
3727         }
3728
3729         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3730
3731         /*
3732          *      We are now using the change value, and
3733          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3734          *      I don't have a global notification system, I'm sending back all the
3735          *      informations even when _NOTHING_ has changed.
3736          */
3737
3738         /* We need to keep track of the change value to send back in
3739            RRPCN replies otherwise our updates are ignored. */
3740
3741         Printer->notify.fnpcn = True;
3742
3743         if (Printer->notify.client_connected) {
3744                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3745                         "Saving change value in request [%x]\n",
3746                         r->in.change_low));
3747                 Printer->notify.change = r->in.change_low;
3748         }
3749
3750         /* just ignore the spoolss_NotifyOption */
3751
3752         switch (Printer->printer_type) {
3753                 case SPLHND_SERVER:
3754                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3755                         break;
3756
3757                 case SPLHND_PRINTER:
3758                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3759                         break;
3760         }
3761
3762         Printer->notify.fnpcn = False;
3763
3764 done:
3765         return result;
3766 }
3767
3768 /********************************************************************
3769  * construct_printer_info_0
3770  * fill a printer_info_0 struct
3771  ********************************************************************/
3772
3773 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3774                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3775                                       struct spoolss_PrinterInfo0 *r,
3776                                       int snum)
3777 {
3778         int count;
3779         counter_printer_0 *session_counter;
3780         time_t setuptime;
3781         print_status_struct status;
3782
3783         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3784         W_ERROR_HAVE_NO_MEMORY(r->printername);
3785
3786         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3787         W_ERROR_HAVE_NO_MEMORY(r->servername);
3788
3789         count = print_queue_length(snum, &status);
3790
3791         /* check if we already have a counter for this printer */
3792         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3793                 if (session_counter->snum == snum)
3794                         break;
3795         }
3796
3797         /* it's the first time, add it to the list */
3798         if (session_counter == NULL) {
3799                 session_counter = SMB_MALLOC_P(counter_printer_0);
3800                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3801                 ZERO_STRUCTP(session_counter);
3802                 session_counter->snum           = snum;
3803                 session_counter->counter        = 0;
3804                 DLIST_ADD(counter_list, session_counter);
3805         }
3806
3807         /* increment it */
3808         session_counter->counter++;
3809
3810         r->cjobs                        = count;
3811         r->total_jobs                   = 0;
3812         r->total_bytes                  = 0;
3813
3814         setuptime = (time_t)ntprinter->info_2->setuptime;
3815
3816         init_systemtime(&r->time, gmtime(&setuptime));
3817
3818         /* JFM:
3819          * the global_counter should be stored in a TDB as it's common to all the clients
3820          * and should be zeroed on samba startup
3821          */
3822         r->global_counter               = session_counter->counter;
3823         r->total_pages                  = 0;
3824         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3825         r->version                      = 0x0005;       /* NT 5 */
3826         r->free_build                   = 0x0893;       /* build 2195 */
3827         r->spooling                     = 0;
3828         r->max_spooling                 = 0;
3829         r->session_counter              = session_counter->counter;
3830         r->num_error_out_of_paper       = 0x0;
3831         r->num_error_not_ready          = 0x0;          /* number of print failure */
3832         r->job_error                    = 0x0;
3833         r->number_of_processors         = 0x1;
3834         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3835         r->high_part_total_bytes        = 0x0;
3836         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3837         r->last_error                   = WERR_OK;
3838         r->status                       = nt_printq_status(status.status);
3839         r->enumerate_network_printers   = 0x0;
3840         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3841         r->processor_architecture       = 0x0;
3842         r->processor_level              = 0x6;          /* 6  ???*/
3843         r->ref_ic                       = 0;
3844         r->reserved2                    = 0;
3845         r->reserved3                    = 0;
3846
3847         return WERR_OK;
3848 }
3849
3850 /****************************************************************************
3851  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3852  should be valid upon entry
3853 ****************************************************************************/
3854
3855 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3856                                     struct spoolss_DeviceMode *r,
3857                                     const NT_DEVICEMODE *ntdevmode)
3858 {
3859         if (!r || !ntdevmode) {
3860                 return WERR_INVALID_PARAM;
3861         }
3862
3863         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3864         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3865
3866         r->specversion          = ntdevmode->specversion;
3867         r->driverversion        = ntdevmode->driverversion;
3868         r->size                 = ntdevmode->size;
3869         r->__driverextra_length = ntdevmode->driverextra;
3870         r->fields               = ntdevmode->fields;
3871
3872         r->orientation          = ntdevmode->orientation;
3873         r->papersize            = ntdevmode->papersize;
3874         r->paperlength          = ntdevmode->paperlength;
3875         r->paperwidth           = ntdevmode->paperwidth;
3876         r->scale                = ntdevmode->scale;
3877         r->copies               = ntdevmode->copies;
3878         r->defaultsource        = ntdevmode->defaultsource;
3879         r->printquality         = ntdevmode->printquality;
3880         r->color                = ntdevmode->color;
3881         r->duplex               = ntdevmode->duplex;
3882         r->yresolution          = ntdevmode->yresolution;
3883         r->ttoption             = ntdevmode->ttoption;
3884         r->collate              = ntdevmode->collate;
3885
3886         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3887         W_ERROR_HAVE_NO_MEMORY(r->formname);
3888
3889         /* all 0 below are values that have not been set in the old parsing/copy
3890          * function, maybe they should... - gd */
3891
3892         r->logpixels            = 0;
3893         r->bitsperpel           = 0;
3894         r->pelswidth            = 0;
3895         r->pelsheight           = 0;
3896         r->displayflags         = 0;
3897         r->displayfrequency     = 0;
3898         r->icmmethod            = ntdevmode->icmmethod;
3899         r->icmintent            = ntdevmode->icmintent;
3900         r->mediatype            = ntdevmode->mediatype;
3901         r->dithertype           = ntdevmode->dithertype;
3902         r->reserved1            = 0;
3903         r->reserved2            = 0;
3904         r->panningwidth         = 0;
3905         r->panningheight        = 0;
3906
3907         if (ntdevmode->nt_dev_private != NULL) {
3908                 r->driverextra_data = data_blob_talloc(mem_ctx,
3909                         ntdevmode->nt_dev_private,
3910                         ntdevmode->driverextra);
3911                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3912         }
3913
3914         return WERR_OK;
3915 }
3916
3917
3918 /****************************************************************************
3919  Create a spoolss_DeviceMode struct. Returns talloced memory.
3920 ****************************************************************************/
3921
3922 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3923                                               const char *servicename)
3924 {
3925         WERROR result;
3926         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3927         struct spoolss_DeviceMode *devmode = NULL;
3928
3929         DEBUG(7,("construct_dev_mode\n"));
3930
3931         DEBUGADD(8,("getting printer characteristics\n"));
3932
3933         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3934                 return NULL;
3935
3936         if (!printer->info_2->devmode) {
3937                 DEBUG(5, ("BONG! There was no device mode!\n"));
3938                 goto done;
3939         }
3940
3941         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3942         if (!devmode) {
3943                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3944                 goto done;
3945         }
3946
3947         DEBUGADD(8,("loading DEVICEMODE\n"));
3948
3949         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3950         if (!W_ERROR_IS_OK(result)) {
3951                 TALLOC_FREE(devmode);
3952         }
3953
3954 done:
3955         free_a_printer(&printer,2);
3956
3957         return devmode;
3958 }
3959
3960 /********************************************************************
3961  * construct_printer_info3
3962  * fill a spoolss_PrinterInfo3 struct
3963  ********************************************************************/
3964
3965 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3966                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3967                                       struct spoolss_PrinterInfo3 *r,
3968                                       int snum)
3969 {
3970         /* These are the components of the SD we are returning. */
3971
3972         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3973                 /* don't use talloc_steal() here unless you do a deep steal of all
3974                    the SEC_DESC members */
3975
3976                 r->secdesc = dup_sec_desc(mem_ctx,
3977                                           ntprinter->info_2->secdesc_buf->sd);
3978                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3979         }
3980
3981         return WERR_OK;
3982 }
3983
3984 /********************************************************************
3985  * construct_printer_info4
3986  * fill a spoolss_PrinterInfo4 struct
3987  ********************************************************************/
3988
3989 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3990                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3991                                       struct spoolss_PrinterInfo4 *r,
3992                                       int snum)
3993 {
3994         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3995         W_ERROR_HAVE_NO_MEMORY(r->printername);
3996         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3997         W_ERROR_HAVE_NO_MEMORY(r->servername);
3998
3999         r->attributes   = ntprinter->info_2->attributes;
4000
4001         return WERR_OK;
4002 }
4003
4004 /********************************************************************
4005  * construct_printer_info5
4006  * fill a spoolss_PrinterInfo5 struct
4007  ********************************************************************/
4008
4009 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4010                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4011                                       struct spoolss_PrinterInfo5 *r,
4012                                       int snum)
4013 {
4014         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4015         W_ERROR_HAVE_NO_MEMORY(r->printername);
4016         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4017         W_ERROR_HAVE_NO_MEMORY(r->portname);
4018
4019         r->attributes   = ntprinter->info_2->attributes;
4020
4021         /* these two are not used by NT+ according to MSDN */
4022
4023         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4024         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4025
4026         return WERR_OK;
4027 }
4028
4029 /********************************************************************
4030  * construct_printer_info_6
4031  * fill a spoolss_PrinterInfo6 struct
4032  ********************************************************************/
4033
4034 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4035                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4036                                       struct spoolss_PrinterInfo6 *r,
4037                                       int snum)
4038 {
4039         int count;
4040         print_status_struct status;
4041
4042         count = print_queue_length(snum, &status);
4043
4044         r->status = nt_printq_status(status.status);
4045
4046         return WERR_OK;
4047 }
4048
4049 /********************************************************************
4050  * construct_printer_info7
4051  * fill a spoolss_PrinterInfo7 struct
4052  ********************************************************************/
4053
4054 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4055                                       Printer_entry *print_hnd,
4056                                       struct spoolss_PrinterInfo7 *r,
4057                                       int snum)
4058 {
4059         struct GUID guid;
4060
4061         if (is_printer_published(print_hnd, snum, &guid)) {
4062                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4063                 r->action = DSPRINT_PUBLISH;
4064         } else {
4065                 r->guid = talloc_strdup(mem_ctx, "");
4066                 r->action = DSPRINT_UNPUBLISH;
4067         }
4068         W_ERROR_HAVE_NO_MEMORY(r->guid);
4069
4070         return WERR_OK;
4071 }
4072
4073 /********************************************************************
4074  * construct_printer_info1
4075  * fill a spoolss_PrinterInfo1 struct
4076 ********************************************************************/
4077
4078 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4079                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4080                                       uint32_t flags,
4081                                       struct spoolss_PrinterInfo1 *r,
4082                                       int snum)
4083 {
4084         char *chaine = NULL;
4085         r->flags                = flags;
4086
4087         if (*ntprinter->info_2->comment == '\0') {
4088                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4089                 chaine = talloc_asprintf(mem_ctx,
4090                                 "%s,%s,%s", ntprinter->info_2->printername,
4091                                 ntprinter->info_2->drivername, lp_comment(snum));
4092         } else {
4093                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4094                 chaine = talloc_asprintf(mem_ctx,
4095                                 "%s,%s,%s", ntprinter->info_2->printername,
4096                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4097         }
4098         W_ERROR_HAVE_NO_MEMORY(chaine);
4099         W_ERROR_HAVE_NO_MEMORY(r->comment);
4100
4101         r->description          = talloc_strdup(mem_ctx, chaine);
4102         W_ERROR_HAVE_NO_MEMORY(r->description);
4103         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4104         W_ERROR_HAVE_NO_MEMORY(r->name);
4105
4106         return WERR_OK;
4107 }
4108
4109 /********************************************************************
4110  * construct_printer_info2
4111  * fill a spoolss_PrinterInfo2 struct
4112 ********************************************************************/
4113
4114 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4115                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4116                                       struct spoolss_PrinterInfo2 *r,
4117                                       int snum)
4118 {
4119         int count;
4120
4121         print_status_struct status;
4122
4123         count = print_queue_length(snum, &status);
4124
4125         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4126         W_ERROR_HAVE_NO_MEMORY(r->servername);
4127         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4128         W_ERROR_HAVE_NO_MEMORY(r->printername);
4129         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4130         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4131         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4132         W_ERROR_HAVE_NO_MEMORY(r->portname);
4133         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4134         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4135
4136         if (*ntprinter->info_2->comment == '\0') {
4137                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4138         } else {
4139                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4140         }
4141         W_ERROR_HAVE_NO_MEMORY(r->comment);
4142
4143         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4144         W_ERROR_HAVE_NO_MEMORY(r->location);
4145         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4146         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4147         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4148         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4149         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4150         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4151         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4152         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4153
4154         r->attributes           = ntprinter->info_2->attributes;
4155
4156         r->priority             = ntprinter->info_2->priority;
4157         r->defaultpriority      = ntprinter->info_2->default_priority;
4158         r->starttime            = ntprinter->info_2->starttime;
4159         r->untiltime            = ntprinter->info_2->untiltime;
4160         r->status               = nt_printq_status(status.status);
4161         r->cjobs                = count;
4162         r->averageppm           = ntprinter->info_2->averageppm;
4163
4164         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4165         if (!r->devmode) {
4166                 DEBUG(8,("Returning NULL Devicemode!\n"));
4167         }
4168
4169         r->secdesc              = NULL;
4170
4171         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4172                 /* don't use talloc_steal() here unless you do a deep steal of all
4173                    the SEC_DESC members */
4174
4175                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4176         }
4177
4178         return WERR_OK;
4179 }
4180
4181 /********************************************************************
4182 ********************************************************************/
4183
4184 static bool snum_is_shared_printer(int snum)
4185 {
4186         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4187 }
4188
4189 /********************************************************************
4190  Spoolss_enumprinters.
4191 ********************************************************************/
4192
4193 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4194                                        uint32_t flags,
4195                                        union spoolss_PrinterInfo **info_p,
4196                                        uint32_t *count)
4197 {
4198         int snum;
4199         int n_services = lp_numservices();
4200         union spoolss_PrinterInfo *info = NULL;
4201         WERROR result = WERR_OK;
4202
4203         DEBUG(4,("enum_all_printers_info_1\n"));
4204
4205         *count = 0;
4206
4207         for (snum=0; snum<n_services; snum++) {
4208
4209                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4210                 struct spoolss_PrinterInfo1 info1;
4211
4212                 if (!snum_is_shared_printer(snum)) {
4213                         continue;
4214                 }
4215
4216                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4217
4218                 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4219                 if (!W_ERROR_IS_OK(result)) {
4220                         continue;
4221                 }
4222
4223                 result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4224                 free_a_printer(&ntprinter,2);
4225                 if (!W_ERROR_IS_OK(result)) {
4226                         continue;
4227                 }
4228
4229                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4230                                             union spoolss_PrinterInfo,
4231                                             *count + 1);
4232                 if (!info) {
4233                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4234                         result = WERR_NOMEM;
4235                         goto out;
4236                 }
4237
4238                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4239
4240                 info[*count].info1 = info1;
4241                 (*count)++;
4242         }
4243
4244  out:
4245         if (!W_ERROR_IS_OK(result)) {
4246                 TALLOC_FREE(info);
4247                 *count = 0;
4248                 return result;
4249         }
4250
4251         *info_p = info;
4252
4253         return WERR_OK;
4254 }
4255
4256 /********************************************************************
4257  enum_all_printers_info_1_local.
4258 *********************************************************************/
4259
4260 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4261                                              union spoolss_PrinterInfo **info,
4262                                              uint32_t *count)
4263 {
4264         DEBUG(4,("enum_all_printers_info_1_local\n"));
4265
4266         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4267 }
4268
4269 /********************************************************************
4270  enum_all_printers_info_1_name.
4271 *********************************************************************/
4272
4273 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4274                                             const char *name,
4275                                             union spoolss_PrinterInfo **info,
4276                                             uint32_t *count)
4277 {
4278         const char *s = name;
4279
4280         DEBUG(4,("enum_all_printers_info_1_name\n"));
4281
4282         if ((name[0] == '\\') && (name[1] == '\\')) {
4283                 s = name + 2;
4284         }
4285
4286         if (!is_myname_or_ipaddr(s)) {
4287                 return WERR_INVALID_NAME;
4288         }
4289
4290         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4291 }
4292
4293 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4294 /********************************************************************
4295  enum_all_printers_info_1_remote.
4296 *********************************************************************/
4297
4298 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4299 {
4300         PRINTER_INFO_1 *printer;
4301         fstring printername;
4302         fstring desc;
4303         fstring comment;
4304         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4305         WERROR result = WERR_OK;
4306
4307         /* JFM: currently it's more a place holder than anything else.
4308          * In the spooler world there is a notion of server registration.
4309          * the print servers are registered on the PDC (in the same domain)
4310          *
4311          * We should have a TDB here. The registration is done thru an
4312          * undocumented RPC call.
4313          */
4314
4315         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4316                 return WERR_NOMEM;
4317
4318         *returned=1;
4319
4320         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4321         slprintf(desc, sizeof(desc)-1,"%s", name);
4322         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4323
4324         init_unistr(&printer->description, desc);
4325         init_unistr(&printer->name, printername);
4326         init_unistr(&printer->comment, comment);
4327         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4328
4329         /* check the required size. */
4330         *needed += spoolss_size_printer_info_1(printer);
4331
4332         if (*needed > offered) {
4333                 result = WERR_INSUFFICIENT_BUFFER;
4334                 goto out;
4335         }
4336
4337         if (!rpcbuf_alloc_size(buffer, *needed)) {
4338                 result = WERR_NOMEM;
4339                 goto out;
4340         }
4341
4342         /* fill the buffer with the structures */
4343         smb_io_printer_info_1("", buffer, printer, 0);
4344
4345 out:
4346         /* clear memory */
4347         SAFE_FREE(printer);
4348
4349         if ( !W_ERROR_IS_OK(result) )
4350                 *returned = 0;
4351
4352         return result;
4353 }
4354
4355 #endif
4356
4357 /********************************************************************
4358  enum_all_printers_info_1_network.
4359 *********************************************************************/
4360
4361 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4362                                                const char *name,
4363                                                union spoolss_PrinterInfo **info,
4364                                                uint32_t *count)
4365 {
4366         const char *s = name;
4367
4368         DEBUG(4,("enum_all_printers_info_1_network\n"));
4369
4370         /* If we respond to a enum_printers level 1 on our name with flags
4371            set to PRINTER_ENUM_REMOTE with a list of printers then these
4372            printers incorrectly appear in the APW browse list.
4373            Specifically the printers for the server appear at the workgroup
4374            level where all the other servers in the domain are
4375            listed. Windows responds to this call with a
4376            WERR_CAN_NOT_COMPLETE so we should do the same. */
4377
4378         if (name[0] == '\\' && name[1] == '\\') {
4379                  s = name + 2;
4380         }
4381
4382         if (is_myname_or_ipaddr(s)) {
4383                  return WERR_CAN_NOT_COMPLETE;
4384         }
4385
4386         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4387 }
4388
4389 /********************************************************************
4390  * api_spoolss_enumprinters
4391  *
4392  * called from api_spoolss_enumprinters (see this to understand)
4393  ********************************************************************/
4394
4395 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4396                                        union spoolss_PrinterInfo **info_p,
4397                                        uint32_t *count)
4398 {
4399         int snum;
4400         int n_services = lp_numservices();
4401         union spoolss_PrinterInfo *info = NULL;
4402         WERROR result = WERR_OK;
4403
4404         *count = 0;
4405
4406         for (snum=0; snum<n_services; snum++) {
4407
4408                 struct spoolss_PrinterInfo2 info2;
4409                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4410
4411                 if (!snum_is_shared_printer(snum)) {
4412                         continue;
4413                 }
4414
4415                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4416
4417                 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4418                 if (!W_ERROR_IS_OK(result)) {
4419                         continue;
4420                 }
4421
4422                 result = construct_printer_info2(info, ntprinter, &info2, snum);
4423                 free_a_printer(&ntprinter, 2);
4424                 if (!W_ERROR_IS_OK(result)) {
4425                         continue;
4426                 }
4427
4428                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4429                                             union spoolss_PrinterInfo,
4430                                             *count + 1);
4431                 if (!info) {
4432                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4433                         result = WERR_NOMEM;
4434                         goto out;
4435                 }
4436
4437                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4438
4439                 info[*count].info2 = info2;
4440
4441                 (*count)++;
4442         }
4443
4444  out:
4445         if (!W_ERROR_IS_OK(result)) {
4446                 TALLOC_FREE(info);
4447                 *count = 0;
4448                 return result;
4449         }
4450
4451         *info_p = info;
4452
4453         return WERR_OK;
4454 }
4455
4456 /********************************************************************
4457  * handle enumeration of printers at level 1
4458  ********************************************************************/
4459
4460 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4461                                   uint32_t flags,
4462                                   const char *name,
4463                                   union spoolss_PrinterInfo **info,
4464                                   uint32_t *count)
4465 {
4466         /* Not all the flags are equals */
4467
4468         if (flags & PRINTER_ENUM_LOCAL) {
4469                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4470         }
4471
4472         if (flags & PRINTER_ENUM_NAME) {
4473                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4474         }
4475
4476 #if 0   /* JERRY - disabled for now */
4477         if (flags & PRINTER_ENUM_REMOTE) {
4478                 return enum_all_printers_info_1_remote(mem_ctx, name, info, count);
4479         }
4480 #endif
4481
4482         if (flags & PRINTER_ENUM_NETWORK) {
4483                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4484         }
4485
4486         return WERR_OK; /* NT4sp5 does that */
4487 }
4488
4489 /********************************************************************
4490  * handle enumeration of printers at level 2
4491  ********************************************************************/
4492
4493 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4494                                   uint32_t flags,
4495                                   const char *servername,
4496                                   union spoolss_PrinterInfo **info,
4497                                   uint32_t *count)
4498 {
4499         if (flags & PRINTER_ENUM_LOCAL) {
4500                 return enum_all_printers_info_2(mem_ctx, info, count);
4501         }
4502
4503         if (flags & PRINTER_ENUM_NAME) {
4504                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4505                         return WERR_INVALID_NAME;
4506                 }
4507
4508                 return enum_all_printers_info_2(mem_ctx, info, count);
4509         }
4510
4511         if (flags & PRINTER_ENUM_REMOTE) {
4512                 return WERR_UNKNOWN_LEVEL;
4513         }
4514
4515         return WERR_OK;
4516 }
4517
4518 /********************************************************************
4519  * handle enumeration of printers at level 5
4520  ********************************************************************/
4521
4522 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4523                                   uint32_t flags,
4524                                   const char *servername,
4525                                   union spoolss_PrinterInfo **info,
4526                                   uint32_t *count)
4527 {
4528 /*      return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4529         return WERR_OK;
4530 }
4531
4532 /****************************************************************
4533  _spoolss_EnumPrinters
4534 ****************************************************************/
4535
4536 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4537                              struct spoolss_EnumPrinters *r)
4538 {
4539         const char *name;
4540         WERROR result;
4541
4542         /* that's an [in out] buffer */
4543
4544         if (!r->in.buffer && (r->in.offered != 0)) {
4545                 return WERR_INVALID_PARAM;
4546         }
4547
4548         DEBUG(4,("_spoolss_EnumPrinters\n"));
4549
4550         *r->out.needed = 0;
4551         *r->out.count = 0;
4552         *r->out.info = NULL;
4553
4554         /*
4555          * Level 1:
4556          *          flags==PRINTER_ENUM_NAME
4557          *           if name=="" then enumerates all printers
4558          *           if name!="" then enumerate the printer
4559          *          flags==PRINTER_ENUM_REMOTE
4560          *          name is NULL, enumerate printers
4561          * Level 2: name!="" enumerates printers, name can't be NULL
4562          * Level 3: doesn't exist
4563          * Level 4: does a local registry lookup
4564          * Level 5: same as Level 2
4565          */
4566
4567         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4568         W_ERROR_HAVE_NO_MEMORY(name);
4569
4570         switch (r->in.level) {
4571         case 1:
4572                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4573                                              r->out.info, r->out.count);
4574                 break;
4575         case 2:
4576                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4577                                              r->out.info, r->out.count);
4578                 break;
4579         case 5:
4580                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4581                                              r->out.info, r->out.count);
4582                 break;
4583         case 3:
4584         case 4:
4585                 result = WERR_OK; /* ??? */
4586                 break;
4587         default:
4588                 return WERR_UNKNOWN_LEVEL;
4589         }
4590
4591         if (!W_ERROR_IS_OK(result)) {
4592                 return result;
4593         }
4594
4595         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4596                                                      spoolss_EnumPrinters, NULL,
4597                                                      *r->out.info, r->in.level,
4598                                                      *r->out.count);
4599         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4600         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4601
4602         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4603 }
4604
4605 /****************************************************************
4606  _spoolss_GetPrinter
4607 ****************************************************************/
4608
4609 WERROR _spoolss_GetPrinter(pipes_struct *p,
4610                            struct spoolss_GetPrinter *r)
4611 {
4612         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4613         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4614         WERROR result = WERR_OK;
4615
4616         int snum;
4617
4618         /* that's an [in out] buffer */
4619
4620         if (!r->in.buffer && (r->in.offered != 0)) {
4621                 return WERR_INVALID_PARAM;
4622         }
4623
4624         *r->out.needed = 0;
4625
4626         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4627                 return WERR_BADFID;
4628         }
4629
4630         result = get_a_printer(Printer, &ntprinter, 2,
4631                                lp_const_servicename(snum));
4632         if (!W_ERROR_IS_OK(result)) {
4633                 return result;
4634         }
4635
4636         switch (r->in.level) {
4637         case 0:
4638                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4639                                                  &r->out.info->info0, snum);
4640                 break;
4641         case 1:
4642                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4643                                                  PRINTER_ENUM_ICON8,
4644                                                  &r->out.info->info1, snum);
4645                 break;
4646         case 2:
4647                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4648                                                  &r->out.info->info2, snum);
4649                 break;
4650         case 3:
4651                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4652                                                  &r->out.info->info3, snum);
4653                 break;
4654         case 4:
4655                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4656                                                  &r->out.info->info4, snum);
4657                 break;
4658         case 5:
4659                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4660                                                  &r->out.info->info5, snum);
4661                 break;
4662         case 6:
4663                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4664                                                  &r->out.info->info6, snum);
4665                 break;
4666         case 7:
4667                 result = construct_printer_info7(p->mem_ctx, Printer,
4668                                                  &r->out.info->info7, snum);
4669                 break;
4670         default:
4671                 result = WERR_UNKNOWN_LEVEL;
4672                 break;
4673         }
4674
4675         free_a_printer(&ntprinter, 2);
4676
4677         if (!W_ERROR_IS_OK(result)) {
4678                 TALLOC_FREE(r->out.info);
4679                 return result;
4680         }
4681
4682         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4683                                                r->out.info, r->in.level);
4684         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4685
4686         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4687 }
4688
4689 /********************************************************************
4690  ********************************************************************/
4691
4692 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4693                                                   fstring *fstring_array,
4694                                                   const char *cservername)
4695 {
4696         int i, num_strings = 0;
4697         const char **array = NULL;
4698
4699         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4700
4701                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4702                                                   cservername, fstring_array[i]);
4703                 if (!str) {
4704                         TALLOC_FREE(array);
4705                         return NULL;
4706                 }
4707
4708
4709                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4710                         TALLOC_FREE(array);
4711                         return NULL;
4712                 }
4713         }
4714
4715         if (i > 0) {
4716                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4717                              &array, &num_strings);
4718         }
4719
4720         return array;
4721 }
4722
4723 /********************************************************************
4724  * fill a spoolss_DriverInfo1 struct
4725  ********************************************************************/
4726
4727 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4728                                         struct spoolss_DriverInfo1 *r,
4729                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4730                                         const char *servername,
4731                                         const char *architecture)
4732 {
4733         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4734         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4735
4736         return WERR_OK;
4737 }
4738
4739 /********************************************************************
4740  * fill a spoolss_DriverInfo2 struct
4741  ********************************************************************/
4742
4743 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4744                                         struct spoolss_DriverInfo2 *r,
4745                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4746                                         const char *servername)
4747
4748 {
4749         const char *cservername = canon_servername(servername);
4750
4751         r->version              = driver->info_3->cversion;
4752
4753         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4754         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4755         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4756         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4757
4758         if (strlen(driver->info_3->driverpath)) {
4759                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4760                                 cservername, driver->info_3->driverpath);
4761         } else {
4762                 r->driver_path  = talloc_strdup(mem_ctx, "");
4763         }
4764         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4765
4766         if (strlen(driver->info_3->datafile)) {
4767                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4768                                 cservername, driver->info_3->datafile);
4769         } else {
4770                 r->data_file    = talloc_strdup(mem_ctx, "");
4771         }
4772         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4773
4774         if (strlen(driver->info_3->configfile)) {
4775                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4776                                 cservername, driver->info_3->configfile);
4777         } else {
4778                 r->config_file  = talloc_strdup(mem_ctx, "");
4779         }
4780         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4781
4782         return WERR_OK;
4783 }
4784
4785 /********************************************************************
4786  * fill a spoolss_DriverInfo3 struct
4787  ********************************************************************/
4788
4789 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4790                                         struct spoolss_DriverInfo3 *r,
4791                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4792                                         const char *servername)
4793 {
4794         const char *cservername = canon_servername(servername);
4795
4796         r->version              = driver->info_3->cversion;
4797
4798         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4799         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4800         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4801         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4802
4803         if (strlen(driver->info_3->driverpath)) {
4804                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4805                                 cservername, driver->info_3->driverpath);
4806         } else {
4807                 r->driver_path  = talloc_strdup(mem_ctx, "");
4808         }
4809         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4810
4811         if (strlen(driver->info_3->datafile)) {
4812                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4813                                 cservername, driver->info_3->datafile);
4814         } else {
4815                 r->data_file    = talloc_strdup(mem_ctx, "");
4816         }
4817         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4818
4819         if (strlen(driver->info_3->configfile)) {
4820                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4821                                 cservername, driver->info_3->configfile);
4822         } else {
4823                 r->config_file  = talloc_strdup(mem_ctx, "");
4824         }
4825         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4826
4827         if (strlen(driver->info_3->helpfile)) {
4828                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4829                                 cservername, driver->info_3->helpfile);
4830         } else {
4831                 r->help_file    = talloc_strdup(mem_ctx, "");
4832         }
4833         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4834
4835         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4836         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4837         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4838         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4839
4840         r->dependent_files = string_array_from_driver_info(mem_ctx,
4841                                                            driver->info_3->dependentfiles,
4842                                                            cservername);
4843         return WERR_OK;
4844 }
4845
4846 /********************************************************************
4847  * fill a spoolss_DriverInfo6 struct
4848  ********************************************************************/
4849
4850 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4851                                         struct spoolss_DriverInfo6 *r,
4852                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4853                                         const char *servername)
4854 {
4855         const char *cservername = canon_servername(servername);
4856
4857         r->version              = driver->info_3->cversion;
4858
4859         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4860         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4861         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4862         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4863
4864         if (strlen(driver->info_3->driverpath)) {
4865                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4866                                 cservername, driver->info_3->driverpath);
4867         } else {
4868                 r->driver_path  = talloc_strdup(mem_ctx, "");
4869         }
4870         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4871
4872         if (strlen(driver->info_3->datafile)) {
4873                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4874                                 cservername, driver->info_3->datafile);
4875         } else {
4876                 r->data_file    = talloc_strdup(mem_ctx, "");
4877         }
4878         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4879
4880         if (strlen(driver->info_3->configfile)) {
4881                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4882                                 cservername, driver->info_3->configfile);
4883         } else {
4884                 r->config_file  = talloc_strdup(mem_ctx, "");
4885         }
4886         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4887
4888         if (strlen(driver->info_3->helpfile)) {
4889                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4890                                 cservername, driver->info_3->helpfile);
4891         } else {
4892                 r->help_file    = talloc_strdup(mem_ctx, "");
4893         }
4894         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4895
4896         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4897         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4898         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4899         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4900
4901         r->dependent_files = string_array_from_driver_info(mem_ctx,
4902                                                            driver->info_3->dependentfiles,
4903                                                            cservername);
4904         r->previous_names = string_array_from_driver_info(mem_ctx,
4905                                                           NULL,
4906                                                           cservername);
4907
4908         r->driver_date          = 0;
4909         r->driver_version       = 0;
4910
4911         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
4912         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4913         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
4914         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4915         r->hardware_id          = talloc_strdup(mem_ctx, "");
4916         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4917         r->provider             = talloc_strdup(mem_ctx, "");
4918         W_ERROR_HAVE_NO_MEMORY(r->provider);
4919
4920         return WERR_OK;
4921 }
4922
4923 /********************************************************************
4924  * construct_printer_driver_info_1
4925  ********************************************************************/
4926
4927 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4928                                               struct spoolss_DriverInfo1 *r,
4929                                               int snum,
4930                                               const char *servername,
4931                                               const char *architecture,
4932                                               uint32_t version)
4933 {
4934         NT_PRINTER_INFO_LEVEL *printer = NULL;
4935         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4936         WERROR result;
4937
4938         ZERO_STRUCT(driver);
4939
4940         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4941                 return WERR_INVALID_PRINTER_NAME;
4942
4943         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4944                 free_a_printer(&printer, 2);
4945                 return WERR_UNKNOWN_PRINTER_DRIVER;
4946         }
4947
4948         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
4949
4950         free_a_printer(&printer,2);
4951
4952         return result;
4953 }
4954
4955 /********************************************************************
4956  * construct_printer_driver_info_2
4957  * fill a printer_info_2 struct
4958  ********************************************************************/
4959
4960 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
4961                                               struct spoolss_DriverInfo2 *r,
4962                                               int snum,
4963                                               const char *servername,
4964                                               const char *architecture,
4965                                               uint32_t version)
4966 {
4967         NT_PRINTER_INFO_LEVEL *printer = NULL;
4968         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4969         WERROR result;
4970
4971         ZERO_STRUCT(printer);
4972         ZERO_STRUCT(driver);
4973
4974         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4975                 return WERR_INVALID_PRINTER_NAME;
4976
4977         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4978                 free_a_printer(&printer, 2);
4979                 return WERR_UNKNOWN_PRINTER_DRIVER;
4980         }
4981
4982         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
4983
4984         free_a_printer(&printer,2);
4985
4986         return result;
4987 }
4988
4989 /********************************************************************
4990  * construct_printer_info_3
4991  * fill a printer_info_3 struct
4992  ********************************************************************/
4993
4994 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
4995                                               struct spoolss_DriverInfo3 *r,
4996                                               int snum,
4997                                               const char *servername,
4998                                               const char *architecture,
4999                                               uint32_t version)
5000 {
5001         NT_PRINTER_INFO_LEVEL *printer = NULL;
5002         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5003         WERROR status;
5004         ZERO_STRUCT(driver);
5005
5006         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5007         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5008         if (!W_ERROR_IS_OK(status))
5009                 return WERR_INVALID_PRINTER_NAME;
5010
5011         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5012         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5013
5014 #if 0   /* JERRY */
5015
5016         /*
5017          * I put this code in during testing.  Helpful when commenting out the
5018          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5019          * as win2k always queries the driver using an infor level of 6.
5020          * I've left it in (but ifdef'd out) because I'll probably
5021          * use it in experimentation again in the future.   --jerry 22/01/2002
5022          */
5023
5024         if (!W_ERROR_IS_OK(status)) {
5025                 /*
5026                  * Is this a W2k client ?
5027                  */
5028                 if (version == 3) {
5029                         /* Yes - try again with a WinNT driver. */
5030                         version = 2;
5031                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5032                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5033                 }
5034 #endif
5035
5036                 if (!W_ERROR_IS_OK(status)) {
5037                         free_a_printer(&printer,2);
5038                         return WERR_UNKNOWN_PRINTER_DRIVER;
5039                 }
5040
5041 #if 0   /* JERRY */
5042         }
5043 #endif
5044
5045
5046         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5047
5048         free_a_printer(&printer,2);
5049
5050         return status;
5051 }
5052
5053 /********************************************************************
5054  * construct_printer_info_6
5055  * fill a printer_info_6 struct
5056  ********************************************************************/
5057
5058 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5059                                               struct spoolss_DriverInfo6 *r,
5060                                               int snum,
5061                                               const char *servername,
5062                                               const char *architecture,
5063                                               uint32_t version)
5064 {
5065         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5066         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5067         WERROR                          status;
5068
5069         ZERO_STRUCT(driver);
5070
5071         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5072
5073         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5074
5075         if (!W_ERROR_IS_OK(status))
5076                 return WERR_INVALID_PRINTER_NAME;
5077
5078         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5079
5080         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5081
5082         if (!W_ERROR_IS_OK(status))
5083         {
5084                 /*
5085                  * Is this a W2k client ?
5086                  */
5087
5088                 if (version < 3) {
5089                         free_a_printer(&printer,2);
5090                         return WERR_UNKNOWN_PRINTER_DRIVER;
5091                 }
5092
5093                 /* Yes - try again with a WinNT driver. */
5094                 version = 2;
5095                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5096                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5097                 if (!W_ERROR_IS_OK(status)) {
5098                         free_a_printer(&printer,2);
5099                         return WERR_UNKNOWN_PRINTER_DRIVER;
5100                 }
5101         }
5102
5103         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5104
5105         free_a_printer(&printer,2);
5106         free_a_printer_driver(driver, 3);
5107
5108         return status;
5109 }
5110
5111 /****************************************************************
5112  _spoolss_GetPrinterDriver2
5113 ****************************************************************/
5114
5115 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5116                                   struct spoolss_GetPrinterDriver2 *r)
5117 {
5118         Printer_entry *printer;
5119         WERROR result;
5120
5121         const char *servername;
5122         int snum;
5123
5124         /* that's an [in out] buffer */
5125
5126         if (!r->in.buffer && (r->in.offered != 0)) {
5127                 return WERR_INVALID_PARAM;
5128         }
5129
5130         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5131
5132         if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5133                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5134                 return WERR_INVALID_PRINTER_NAME;
5135         }
5136
5137         *r->out.needed = 0;
5138         *r->out.server_major_version = 0;
5139         *r->out.server_minor_version = 0;
5140
5141         servername = get_server_name(printer);
5142
5143         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5144                 return WERR_BADFID;
5145         }
5146
5147         switch (r->in.level) {
5148         case 1:
5149                 result = construct_printer_driver_info_1(p->mem_ctx,
5150                                                          &r->out.info->info1,
5151                                                          snum,
5152                                                          servername,
5153                                                          r->in.architecture,
5154                                                          r->in.client_major_version);
5155                 break;
5156         case 2:
5157                 result = construct_printer_driver_info_2(p->mem_ctx,
5158                                                          &r->out.info->info2,
5159                                                          snum,
5160                                                          servername,
5161                                                          r->in.architecture,
5162                                                          r->in.client_major_version);
5163                 break;
5164         case 3:
5165                 result = construct_printer_driver_info_3(p->mem_ctx,
5166                                                          &r->out.info->info3,
5167                                                          snum,
5168                                                          servername,
5169                                                          r->in.architecture,
5170                                                          r->in.client_major_version);
5171                 break;
5172         case 6:
5173                 result = construct_printer_driver_info_6(p->mem_ctx,
5174                                                          &r->out.info->info6,
5175                                                          snum,
5176                                                          servername,
5177                                                          r->in.architecture,
5178                                                          r->in.client_major_version);
5179                 break;
5180         default:
5181 #if 0   /* JERRY */
5182         case 101:
5183                 /* apparently this call is the equivalent of
5184                    EnumPrinterDataEx() for the DsDriver key */
5185                 break;
5186 #endif
5187                 result = WERR_UNKNOWN_LEVEL;
5188                 break;
5189         }
5190
5191         if (!W_ERROR_IS_OK(result)) {
5192                 TALLOC_FREE(r->out.info);
5193                 return result;
5194         }
5195
5196         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5197                                                r->out.info, r->in.level);
5198         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5199
5200         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5201 }
5202
5203
5204 /****************************************************************
5205  _spoolss_StartPagePrinter
5206 ****************************************************************/
5207
5208 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5209                                  struct spoolss_StartPagePrinter *r)
5210 {
5211         POLICY_HND *handle = r->in.handle;
5212
5213         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5214
5215         if (!Printer) {
5216                 DEBUG(3,("_spoolss_StartPagePrinter: "
5217                         "Error in startpageprinter printer handle\n"));
5218                 return WERR_BADFID;
5219         }
5220
5221         Printer->page_started=True;
5222         return WERR_OK;
5223 }
5224
5225 /****************************************************************
5226  _spoolss_EndPagePrinter
5227 ****************************************************************/
5228
5229 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5230                                struct spoolss_EndPagePrinter *r)
5231 {
5232         POLICY_HND *handle = r->in.handle;
5233         int snum;
5234
5235         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5236
5237         if (!Printer) {
5238                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5239                         OUR_HANDLE(handle)));
5240                 return WERR_BADFID;
5241         }
5242
5243         if (!get_printer_snum(p, handle, &snum, NULL))
5244                 return WERR_BADFID;
5245
5246         Printer->page_started=False;
5247         print_job_endpage(snum, Printer->jobid);
5248
5249         return WERR_OK;
5250 }
5251
5252 /****************************************************************
5253  _spoolss_StartDocPrinter
5254 ****************************************************************/
5255
5256 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5257                                 struct spoolss_StartDocPrinter *r)
5258 {
5259         POLICY_HND *handle = r->in.handle;
5260         uint32_t *jobid = r->out.job_id;
5261         struct spoolss_DocumentInfo1 *info_1;
5262         int snum;
5263         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5264
5265         if (!Printer) {
5266                 DEBUG(2,("_spoolss_StartDocPrinter: "
5267                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5268                 return WERR_BADFID;
5269         }
5270
5271         if (r->in.level != 1) {
5272                 return WERR_UNKNOWN_LEVEL;
5273         }
5274
5275         info_1 = r->in.info.info1;
5276
5277         /*
5278          * a nice thing with NT is it doesn't listen to what you tell it.
5279          * when asked to send _only_ RAW datas, it tries to send datas
5280          * in EMF format.
5281          *
5282          * So I add checks like in NT Server ...
5283          */
5284
5285         if (info_1->datatype) {
5286                 if (strcmp(info_1->datatype, "RAW") != 0) {
5287                         (*jobid)=0;
5288                         return WERR_INVALID_DATATYPE;
5289                 }
5290         }
5291
5292         /* get the share number of the printer */
5293         if (!get_printer_snum(p, handle, &snum, NULL)) {
5294                 return WERR_BADFID;
5295         }
5296
5297         Printer->jobid = print_job_start(p->server_info, snum,
5298                                          info_1->document_name,
5299                                          Printer->nt_devmode);
5300
5301         /* An error occured in print_job_start() so return an appropriate
5302            NT error code. */
5303
5304         if (Printer->jobid == -1) {
5305                 return map_werror_from_unix(errno);
5306         }
5307
5308         Printer->document_started=True;
5309         (*jobid) = Printer->jobid;
5310
5311         return WERR_OK;
5312 }
5313
5314 /****************************************************************
5315  _spoolss_EndDocPrinter
5316 ****************************************************************/
5317
5318 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5319                               struct spoolss_EndDocPrinter *r)
5320 {
5321         POLICY_HND *handle = r->in.handle;
5322
5323         return _spoolss_enddocprinter_internal(p, handle);
5324 }
5325
5326 /****************************************************************
5327  _spoolss_WritePrinter
5328 ****************************************************************/
5329
5330 WERROR _spoolss_WritePrinter(pipes_struct *p,
5331                              struct spoolss_WritePrinter *r)
5332 {
5333         POLICY_HND *handle = r->in.handle;
5334         uint32 buffer_size = r->in._data_size;
5335         uint8 *buffer = r->in.data.data;
5336         uint32 *buffer_written = &r->in._data_size;
5337         int snum;
5338         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5339
5340         if (!Printer) {
5341                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5342                         OUR_HANDLE(handle)));
5343                 *r->out.num_written = r->in._data_size;
5344                 return WERR_BADFID;
5345         }
5346
5347         if (!get_printer_snum(p, handle, &snum, NULL))
5348                 return WERR_BADFID;
5349
5350         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5351                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5352         if (*buffer_written == (uint32)-1) {
5353                 *r->out.num_written = 0;
5354                 if (errno == ENOSPC)
5355                         return WERR_NO_SPOOL_SPACE;
5356                 else
5357                         return WERR_ACCESS_DENIED;
5358         }
5359
5360         *r->out.num_written = r->in._data_size;
5361
5362         return WERR_OK;
5363 }
5364
5365 /********************************************************************
5366  * api_spoolss_getprinter
5367  * called from the spoolss dispatcher
5368  *
5369  ********************************************************************/
5370
5371 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5372                               pipes_struct *p)
5373 {
5374         int snum;
5375         WERROR errcode = WERR_BADFUNC;
5376         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5377
5378         if (!Printer) {
5379                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5380                 return WERR_BADFID;
5381         }
5382
5383         if (!get_printer_snum(p, handle, &snum, NULL))
5384                 return WERR_BADFID;
5385
5386         switch (command) {
5387         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5388                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5389                         errcode = WERR_OK;
5390                 }
5391                 break;
5392         case SPOOLSS_PRINTER_CONTROL_RESUME:
5393         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5394                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5395                         errcode = WERR_OK;
5396                 }
5397                 break;
5398         case SPOOLSS_PRINTER_CONTROL_PURGE:
5399                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5400                         errcode = WERR_OK;
5401                 }
5402                 break;
5403         default:
5404                 return WERR_UNKNOWN_LEVEL;
5405         }
5406
5407         return errcode;
5408 }
5409
5410
5411 /****************************************************************
5412  _spoolss_AbortPrinter
5413  * From MSDN: "Deletes printer's spool file if printer is configured
5414  * for spooling"
5415 ****************************************************************/
5416
5417 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5418                              struct spoolss_AbortPrinter *r)
5419 {
5420         POLICY_HND      *handle = r->in.handle;
5421         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5422         int             snum;
5423         WERROR          errcode = WERR_OK;
5424
5425         if (!Printer) {
5426                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5427                         OUR_HANDLE(handle)));
5428                 return WERR_BADFID;
5429         }
5430
5431         if (!get_printer_snum(p, handle, &snum, NULL))
5432                 return WERR_BADFID;
5433
5434         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5435
5436         return errcode;
5437 }
5438
5439 /********************************************************************
5440  * called by spoolss_api_setprinter
5441  * when updating a printer description
5442  ********************************************************************/
5443
5444 static WERROR update_printer_sec(POLICY_HND *handle,
5445                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5446 {
5447         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5448         WERROR result;
5449         int snum;
5450
5451         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5452
5453         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5454                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5455                          OUR_HANDLE(handle)));
5456
5457                 result = WERR_BADFID;
5458                 goto done;
5459         }
5460
5461         if (!secdesc_ctr) {
5462                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5463                 result = WERR_INVALID_PARAM;
5464                 goto done;
5465         }
5466
5467         /* Check the user has permissions to change the security
5468            descriptor.  By experimentation with two NT machines, the user
5469            requires Full Access to the printer to change security
5470            information. */
5471
5472         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5473                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5474                 result = WERR_ACCESS_DENIED;
5475                 goto done;
5476         }
5477
5478         /* NT seems to like setting the security descriptor even though
5479            nothing may have actually changed. */
5480
5481         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5482                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5483                 result = WERR_BADFID;
5484                 goto done;
5485         }
5486
5487         if (DEBUGLEVEL >= 10) {
5488                 SEC_ACL *the_acl;
5489                 int i;
5490
5491                 the_acl = old_secdesc_ctr->sd->dacl;
5492                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5493                            PRINTERNAME(snum), the_acl->num_aces));
5494
5495                 for (i = 0; i < the_acl->num_aces; i++) {
5496                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5497                                            &the_acl->aces[i].trustee),
5498                                   the_acl->aces[i].access_mask));
5499                 }
5500
5501                 the_acl = secdesc_ctr->sd->dacl;
5502
5503                 if (the_acl) {
5504                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5505                                    PRINTERNAME(snum), the_acl->num_aces));
5506
5507                         for (i = 0; i < the_acl->num_aces; i++) {
5508                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5509                                                    &the_acl->aces[i].trustee),
5510                                            the_acl->aces[i].access_mask));
5511                         }
5512                 } else {
5513                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5514                 }
5515         }
5516
5517         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5518         if (!new_secdesc_ctr) {
5519                 result = WERR_NOMEM;
5520                 goto done;
5521         }
5522
5523         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5524                 result = WERR_OK;
5525                 goto done;
5526         }
5527
5528         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5529
5530  done:
5531
5532         return result;
5533 }
5534
5535 /********************************************************************
5536  Canonicalize printer info from a client
5537
5538  ATTN: It does not matter what we set the servername to hear
5539  since we do the necessary work in get_a_printer() to set it to
5540  the correct value based on what the client sent in the
5541  _spoolss_open_printer_ex().
5542  ********************************************************************/
5543
5544 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5545 {
5546         fstring printername;
5547         const char *p;
5548
5549         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5550                 "portname=%s drivername=%s comment=%s location=%s\n",
5551                 info->servername, info->printername, info->sharename,
5552                 info->portname, info->drivername, info->comment, info->location));
5553
5554         /* we force some elements to "correct" values */
5555         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5556         fstrcpy(info->sharename, lp_servicename(snum));
5557
5558         /* check to see if we allow printername != sharename */
5559
5560         if ( lp_force_printername(snum) ) {
5561                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5562                         global_myname(), info->sharename );
5563         } else {
5564
5565                 /* make sure printername is in \\server\printername format */
5566
5567                 fstrcpy( printername, info->printername );
5568                 p = printername;
5569                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5570                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5571                                 p++;
5572                 }
5573
5574                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5575                          global_myname(), p );
5576         }
5577
5578         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5579         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5580
5581
5582
5583         return True;
5584 }
5585
5586 /****************************************************************************
5587 ****************************************************************************/
5588
5589 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5590 {
5591         char *cmd = lp_addport_cmd();
5592         char *command = NULL;
5593         int ret;
5594         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5595         bool is_print_op = False;
5596
5597         if ( !*cmd ) {
5598                 return WERR_ACCESS_DENIED;
5599         }
5600
5601         command = talloc_asprintf(ctx,
5602                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5603         if (!command) {
5604                 return WERR_NOMEM;
5605         }
5606
5607         if ( token )
5608                 is_print_op = user_has_privileges( token, &se_printop );
5609
5610         DEBUG(10,("Running [%s]\n", command));
5611
5612         /********* BEGIN SePrintOperatorPrivilege **********/
5613
5614         if ( is_print_op )
5615                 become_root();
5616
5617         ret = smbrun(command, NULL);
5618
5619         if ( is_print_op )
5620                 unbecome_root();
5621
5622         /********* END SePrintOperatorPrivilege **********/
5623
5624         DEBUGADD(10,("returned [%d]\n", ret));
5625
5626         TALLOC_FREE(command);
5627
5628         if ( ret != 0 ) {
5629                 return WERR_ACCESS_DENIED;
5630         }
5631
5632         return WERR_OK;
5633 }
5634
5635 /****************************************************************************
5636 ****************************************************************************/
5637
5638 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5639 {
5640         char *cmd = lp_addprinter_cmd();
5641         char **qlines;
5642         char *command = NULL;
5643         int numlines;
5644         int ret;
5645         int fd;
5646         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5647         bool is_print_op = False;
5648         char *remote_machine = talloc_strdup(ctx, "%m");
5649
5650         if (!remote_machine) {
5651                 return false;
5652         }
5653         remote_machine = talloc_sub_basic(ctx,
5654                                 current_user_info.smb_name,
5655                                 current_user_info.domain,
5656                                 remote_machine);
5657         if (!remote_machine) {
5658                 return false;
5659         }
5660
5661         command = talloc_asprintf(ctx,
5662                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5663                         cmd, printer->info_2->printername, printer->info_2->sharename,
5664                         printer->info_2->portname, printer->info_2->drivername,
5665                         printer->info_2->location, printer->info_2->comment, remote_machine);
5666         if (!command) {
5667                 return false;
5668         }
5669
5670         if ( token )
5671                 is_print_op = user_has_privileges( token, &se_printop );
5672
5673         DEBUG(10,("Running [%s]\n", command));
5674
5675         /********* BEGIN SePrintOperatorPrivilege **********/
5676
5677         if ( is_print_op )
5678                 become_root();
5679
5680         if ( (ret = smbrun(command, &fd)) == 0 ) {
5681                 /* Tell everyone we updated smb.conf. */
5682                 message_send_all(smbd_messaging_context(),
5683                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5684         }
5685
5686         if ( is_print_op )
5687                 unbecome_root();
5688
5689         /********* END SePrintOperatorPrivilege **********/
5690
5691         DEBUGADD(10,("returned [%d]\n", ret));
5692
5693         TALLOC_FREE(command);
5694         TALLOC_FREE(remote_machine);
5695
5696         if ( ret != 0 ) {
5697                 if (fd != -1)
5698                         close(fd);
5699                 return False;
5700         }
5701
5702         /* reload our services immediately */
5703         reload_services( False );
5704
5705         numlines = 0;
5706         /* Get lines and convert them back to dos-codepage */
5707         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5708         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5709         close(fd);
5710
5711         /* Set the portname to what the script says the portname should be. */
5712         /* but don't require anything to be return from the script exit a good error code */
5713
5714         if (numlines) {
5715                 /* Set the portname to what the script says the portname should be. */
5716                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5717                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5718         }
5719
5720         TALLOC_FREE(qlines);
5721         return True;
5722 }
5723
5724
5725 /********************************************************************
5726  * Called by spoolss_api_setprinter
5727  * when updating a printer description.
5728  ********************************************************************/
5729
5730 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
5731                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5732                              struct spoolss_DeviceMode *devmode)
5733 {
5734         int snum;
5735         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5736         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5737         WERROR result;
5738         UNISTR2 buffer;
5739         fstring asc_buffer;
5740
5741         DEBUG(8,("update_printer\n"));
5742
5743         result = WERR_OK;
5744
5745         if (!Printer) {
5746                 result = WERR_BADFID;
5747                 goto done;
5748         }
5749
5750         if (!get_printer_snum(p, handle, &snum, NULL)) {
5751                 result = WERR_BADFID;
5752                 goto done;
5753         }
5754
5755         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5756             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5757                 result = WERR_BADFID;
5758                 goto done;
5759         }
5760
5761         DEBUGADD(8,("Converting info_2 struct\n"));
5762
5763         /*
5764          * convert_printer_info converts the incoming
5765          * info from the client and overwrites the info
5766          * just read from the tdb in the pointer 'printer'.
5767          */
5768
5769         if (!convert_printer_info(info_ctr, printer)) {
5770                 result =  WERR_NOMEM;
5771                 goto done;
5772         }
5773
5774         if (devmode) {
5775                 /* we have a valid devmode
5776                    convert it and link it*/
5777
5778                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5779                 if (!convert_devicemode(printer->info_2->printername, devmode,
5780                                         &printer->info_2->devmode)) {
5781                         result =  WERR_NOMEM;
5782                         goto done;
5783                 }
5784         }
5785
5786         /* Do sanity check on the requested changes for Samba */
5787
5788         if (!check_printer_ok(printer->info_2, snum)) {
5789                 result = WERR_INVALID_PARAM;
5790                 goto done;
5791         }
5792
5793         /* FIXME!!! If the driver has changed we really should verify that
5794            it is installed before doing much else   --jerry */
5795
5796         /* Check calling user has permission to update printer description */
5797
5798         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5799                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5800                 result = WERR_ACCESS_DENIED;
5801                 goto done;
5802         }
5803
5804         /* Call addprinter hook */
5805         /* Check changes to see if this is really needed */
5806
5807         if ( *lp_addprinter_cmd()
5808                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5809                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5810                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5811                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5812         {
5813                 /* add_printer_hook() will call reload_services() */
5814
5815                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5816                                        printer) ) {
5817                         result = WERR_ACCESS_DENIED;
5818                         goto done;
5819                 }
5820         }
5821
5822         /*
5823          * When a *new* driver is bound to a printer, the drivername is used to
5824          * lookup previously saved driver initialization info, which is then
5825          * bound to the printer, simulating what happens in the Windows arch.
5826          */
5827         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5828         {
5829                 if (!set_driver_init(printer, 2))
5830                 {
5831                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5832                                 printer->info_2->drivername));
5833                 }
5834
5835                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5836                         printer->info_2->drivername));
5837
5838                 notify_printer_driver(snum, printer->info_2->drivername);
5839         }
5840
5841         /*
5842          * flag which changes actually occured.  This is a small subset of
5843          * all the possible changes.  We also have to update things in the
5844          * DsSpooler key.
5845          */
5846
5847         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5848                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
5849                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5850                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5851
5852                 notify_printer_comment(snum, printer->info_2->comment);
5853         }
5854
5855         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5856                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
5857                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5858                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5859
5860                 notify_printer_sharename(snum, printer->info_2->sharename);
5861         }
5862
5863         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5864                 char *pname;
5865
5866                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5867                         pname++;
5868                 else
5869                         pname = printer->info_2->printername;
5870
5871
5872                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
5873                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5874                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5875
5876                 notify_printer_printername( snum, pname );
5877         }
5878
5879         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5880                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
5881                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5882                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5883
5884                 notify_printer_port(snum, printer->info_2->portname);
5885         }
5886
5887         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5888                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
5889                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5890                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5891
5892                 notify_printer_location(snum, printer->info_2->location);
5893         }
5894
5895         /* here we need to update some more DsSpooler keys */
5896         /* uNCName, serverName, shortServerName */
5897
5898         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
5899         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5900                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5901         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5902                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5903
5904         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5905                  global_myname(), printer->info_2->sharename );
5906         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
5907         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5908                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5909
5910         /* Update printer info */
5911         result = mod_a_printer(printer, 2);
5912
5913 done:
5914         free_a_printer(&printer, 2);
5915         free_a_printer(&old_printer, 2);
5916
5917
5918         return result;
5919 }
5920
5921 /****************************************************************************
5922 ****************************************************************************/
5923 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5924                                            struct spoolss_SetPrinterInfo7 *info7)
5925 {
5926 #ifdef HAVE_ADS
5927         int snum;
5928         Printer_entry *Printer;
5929
5930         if ( lp_security() != SEC_ADS ) {
5931                 return WERR_UNKNOWN_LEVEL;
5932         }
5933
5934         Printer = find_printer_index_by_hnd(p, handle);
5935
5936         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5937
5938         if (!Printer)
5939                 return WERR_BADFID;
5940
5941         if (!get_printer_snum(p, handle, &snum, NULL))
5942                 return WERR_BADFID;
5943
5944         nt_printer_publish(Printer, snum, info7->action);
5945
5946         return WERR_OK;
5947 #else
5948         return WERR_UNKNOWN_LEVEL;
5949 #endif
5950 }
5951
5952 /****************************************************************
5953  _spoolss_SetPrinter
5954 ****************************************************************/
5955
5956 WERROR _spoolss_SetPrinter(pipes_struct *p,
5957                            struct spoolss_SetPrinter *r)
5958 {
5959         POLICY_HND *handle = r->in.handle;
5960         WERROR result;
5961
5962         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5963
5964         if (!Printer) {
5965                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5966                         OUR_HANDLE(handle)));
5967                 return WERR_BADFID;
5968         }
5969
5970         /* check the level */
5971         switch (r->in.info_ctr->level) {
5972                 case 0:
5973                         return control_printer(handle, r->in.command, p);
5974                 case 2:
5975                         result = update_printer(p, handle,
5976                                                 r->in.info_ctr,
5977                                                 r->in.devmode_ctr->devmode);
5978                         if (!W_ERROR_IS_OK(result))
5979                                 return result;
5980                         if (r->in.secdesc_ctr->sd)
5981                                 result = update_printer_sec(handle, p,
5982                                                             r->in.secdesc_ctr);
5983                         return result;
5984                 case 3:
5985                         return update_printer_sec(handle, p,
5986                                                   r->in.secdesc_ctr);
5987                 case 7:
5988                         return publish_or_unpublish_printer(p, handle,
5989                                                             r->in.info_ctr->info.info7);
5990                 default:
5991                         return WERR_UNKNOWN_LEVEL;
5992         }
5993 }
5994
5995 /****************************************************************
5996  _spoolss_FindClosePrinterNotify
5997 ****************************************************************/
5998
5999 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6000                                        struct spoolss_FindClosePrinterNotify *r)
6001 {
6002         POLICY_HND *handle = r->in.handle;
6003         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6004
6005         if (!Printer) {
6006                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6007                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6008                 return WERR_BADFID;
6009         }
6010
6011         if (Printer->notify.client_connected==True) {
6012                 int snum = -1;
6013
6014                 if ( Printer->printer_type == SPLHND_SERVER)
6015                         snum = -1;
6016                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6017                                 !get_printer_snum(p, handle, &snum, NULL) )
6018                         return WERR_BADFID;
6019
6020                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6021         }
6022
6023         Printer->notify.flags=0;
6024         Printer->notify.options=0;
6025         Printer->notify.localmachine[0]='\0';
6026         Printer->notify.printerlocal=0;
6027         TALLOC_FREE(Printer->notify.option);
6028         Printer->notify.client_connected=False;
6029
6030         return WERR_OK;
6031 }
6032
6033 /****************************************************************
6034  _spoolss_AddJob
6035 ****************************************************************/
6036
6037 WERROR _spoolss_AddJob(pipes_struct *p,
6038                        struct spoolss_AddJob *r)
6039 {
6040         if (!r->in.buffer && (r->in.offered != 0)) {
6041                 return WERR_INVALID_PARAM;
6042         }
6043
6044         /* this is what a NT server returns for AddJob. AddJob must fail on
6045          * non-local printers */
6046
6047         if (r->in.level != 1) {
6048                 return WERR_UNKNOWN_LEVEL;
6049         }
6050
6051         return WERR_INVALID_PARAM;
6052 }
6053
6054 /****************************************************************************
6055 fill_job_info1
6056 ****************************************************************************/
6057
6058 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6059                              struct spoolss_JobInfo1 *r,
6060                              const print_queue_struct *queue,
6061                              int position, int snum,
6062                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6063 {
6064         struct tm *t;
6065
6066         t = gmtime(&queue->time);
6067
6068         r->job_id               = queue->job;
6069
6070         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6071         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6072         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6073         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6074         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6075         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6076         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6077         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6078         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6079         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6080         r->text_status          = talloc_strdup(mem_ctx, "");
6081         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6082
6083         r->status               = nt_printj_status(queue->status);
6084         r->priority             = queue->priority;
6085         r->position             = position;
6086         r->total_pages          = queue->page_count;
6087         r->pages_printed        = 0; /* ??? */
6088
6089         init_systemtime(&r->submitted, t);
6090
6091         return WERR_OK;
6092 }
6093
6094 /****************************************************************************
6095 fill_job_info2
6096 ****************************************************************************/
6097
6098 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6099                              struct spoolss_JobInfo2 *r,
6100                              const print_queue_struct *queue,
6101                              int position, int snum,
6102                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6103                              struct spoolss_DeviceMode *devmode)
6104 {
6105         struct tm *t;
6106
6107         t = gmtime(&queue->time);
6108
6109         r->job_id               = queue->job;
6110
6111         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6112         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6113         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6114         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6115         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6116         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6117         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6118         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6119         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6120         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6121         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6122         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6123         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6124         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6125         r->parameters           = talloc_strdup(mem_ctx, "");
6126         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6127         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6128         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6129
6130         r->devmode              = devmode;
6131
6132         r->text_status          = talloc_strdup(mem_ctx, "");
6133         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6134
6135         r->secdesc              = NULL;
6136
6137         r->status               = nt_printj_status(queue->status);
6138         r->priority             = queue->priority;
6139         r->position             = position;
6140         r->start_time           = 0;
6141         r->until_time           = 0;
6142         r->total_pages          = queue->page_count;
6143         r->size                 = queue->size;
6144         init_systemtime(&r->submitted, t);
6145         r->time                 = 0;
6146         r->pages_printed        = 0; /* ??? */
6147
6148         return WERR_OK;
6149 }
6150
6151 /****************************************************************************
6152  Enumjobs at level 1.
6153 ****************************************************************************/
6154
6155 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6156                               const print_queue_struct *queue,
6157                               uint32_t num_queues, int snum,
6158                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6159                               union spoolss_JobInfo **info_p,
6160                               uint32_t *count)
6161 {
6162         union spoolss_JobInfo *info;
6163         int i;
6164         WERROR result = WERR_OK;
6165
6166         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6167         W_ERROR_HAVE_NO_MEMORY(info);
6168
6169         *count = num_queues;
6170
6171         for (i=0; i<*count; i++) {
6172                 result = fill_job_info1(info,
6173                                         &info[i].info1,
6174                                         &queue[i],
6175                                         i,
6176                                         snum,
6177                                         ntprinter);
6178                 if (!W_ERROR_IS_OK(result)) {
6179                         goto out;
6180                 }
6181         }
6182
6183  out:
6184         if (!W_ERROR_IS_OK(result)) {
6185                 TALLOC_FREE(info);
6186                 *count = 0;
6187                 return result;
6188         }
6189
6190         *info_p = info;
6191
6192         return WERR_OK;
6193 }
6194
6195 /****************************************************************************
6196  Enumjobs at level 2.
6197 ****************************************************************************/
6198
6199 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6200                               const print_queue_struct *queue,
6201                               uint32_t num_queues, int snum,
6202                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6203                               union spoolss_JobInfo **info_p,
6204                               uint32_t *count)
6205 {
6206         union spoolss_JobInfo *info;
6207         int i;
6208         WERROR result = WERR_OK;
6209
6210         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6211         W_ERROR_HAVE_NO_MEMORY(info);
6212
6213         *count = num_queues;
6214
6215         for (i=0; i<*count; i++) {
6216
6217                 struct spoolss_DeviceMode *devmode;
6218
6219                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6220                 if (!devmode) {
6221                         result = WERR_NOMEM;
6222                         goto out;
6223                 }
6224
6225                 result = fill_job_info2(info,
6226                                         &info[i].info2,
6227                                         &queue[i],
6228                                         i,
6229                                         snum,
6230                                         ntprinter,
6231                                         devmode);
6232                 if (!W_ERROR_IS_OK(result)) {
6233                         goto out;
6234                 }
6235         }
6236
6237  out:
6238         if (!W_ERROR_IS_OK(result)) {
6239                 TALLOC_FREE(info);
6240                 *count = 0;
6241                 return result;
6242         }
6243
6244         *info_p = info;
6245
6246         return WERR_OK;
6247 }
6248
6249 /****************************************************************
6250  _spoolss_EnumJobs
6251 ****************************************************************/
6252
6253 WERROR _spoolss_EnumJobs(pipes_struct *p,
6254                          struct spoolss_EnumJobs *r)
6255 {
6256         WERROR result;
6257         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6258         int snum;
6259         print_status_struct prt_status;
6260         print_queue_struct *queue = NULL;
6261         uint32_t count;
6262
6263         /* that's an [in out] buffer */
6264
6265         if (!r->in.buffer && (r->in.offered != 0)) {
6266                 return WERR_INVALID_PARAM;
6267         }
6268
6269         DEBUG(4,("_spoolss_EnumJobs\n"));
6270
6271         *r->out.needed = 0;
6272         *r->out.count = 0;
6273         *r->out.info = NULL;
6274
6275         /* lookup the printer snum and tdb entry */
6276
6277         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6278                 return WERR_BADFID;
6279         }
6280
6281         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6282         if (!W_ERROR_IS_OK(result)) {
6283                 return result;
6284         }
6285
6286         count = print_queue_status(snum, &queue, &prt_status);
6287         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6288                 count, prt_status.status, prt_status.message));
6289
6290         if (count == 0) {
6291                 SAFE_FREE(queue);
6292                 free_a_printer(&ntprinter, 2);
6293                 return WERR_OK;
6294         }
6295
6296         switch (r->in.level) {
6297         case 1:
6298                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6299                                          ntprinter, r->out.info, r->out.count);
6300                 break;
6301         case 2:
6302                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6303                                          ntprinter, r->out.info, r->out.count);
6304                 break;
6305         default:
6306                 result = WERR_UNKNOWN_LEVEL;
6307                 break;
6308         }
6309
6310         SAFE_FREE(queue);
6311         free_a_printer(&ntprinter, 2);
6312
6313         if (!W_ERROR_IS_OK(result)) {
6314                 return result;
6315         }
6316
6317         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6318                                                      spoolss_EnumJobs, NULL,
6319                                                      *r->out.info, r->in.level,
6320                                                      *r->out.count);
6321         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6322         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6323
6324         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6325 }
6326
6327 /****************************************************************
6328  _spoolss_ScheduleJob
6329 ****************************************************************/
6330
6331 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6332                             struct spoolss_ScheduleJob *r)
6333 {
6334         return WERR_OK;
6335 }
6336
6337 /****************************************************************
6338  _spoolss_SetJob
6339 ****************************************************************/
6340
6341 WERROR _spoolss_SetJob(pipes_struct *p,
6342                        struct spoolss_SetJob *r)
6343 {
6344         POLICY_HND *handle = r->in.handle;
6345         uint32 jobid = r->in.job_id;
6346         uint32 command = r->in.command;
6347
6348         int snum;
6349         WERROR errcode = WERR_BADFUNC;
6350
6351         if (!get_printer_snum(p, handle, &snum, NULL)) {
6352                 return WERR_BADFID;
6353         }
6354
6355         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6356                 return WERR_INVALID_PRINTER_NAME;
6357         }
6358
6359         switch (command) {
6360         case SPOOLSS_JOB_CONTROL_CANCEL:
6361         case SPOOLSS_JOB_CONTROL_DELETE:
6362                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6363                         errcode = WERR_OK;
6364                 }
6365                 break;
6366         case SPOOLSS_JOB_CONTROL_PAUSE:
6367                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6368                         errcode = WERR_OK;
6369                 }
6370                 break;
6371         case SPOOLSS_JOB_CONTROL_RESTART:
6372         case SPOOLSS_JOB_CONTROL_RESUME:
6373                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6374                         errcode = WERR_OK;
6375                 }
6376                 break;
6377         default:
6378                 return WERR_UNKNOWN_LEVEL;
6379         }
6380
6381         return errcode;
6382 }
6383
6384 /****************************************************************************
6385  Enumerates all printer drivers at level 1.
6386 ****************************************************************************/
6387
6388 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6389                                         const char *servername,
6390                                         const char *architecture,
6391                                         union spoolss_DriverInfo **info_p,
6392                                         uint32_t *count)
6393 {
6394         int i;
6395         int ndrivers;
6396         uint32_t version;
6397         fstring *list = NULL;
6398         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6399         union spoolss_DriverInfo *info = NULL;
6400         WERROR result = WERR_OK;
6401
6402         *count = 0;
6403
6404         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6405                 list = NULL;
6406                 ndrivers = get_ntdrivers(&list, architecture, version);
6407                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6408                         ndrivers, architecture, version));
6409
6410                 if (ndrivers == -1) {
6411                         result = WERR_NOMEM;
6412                         goto out;
6413                 }
6414
6415                 if (ndrivers != 0) {
6416                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6417                                                     union spoolss_DriverInfo,
6418                                                     *count + ndrivers);
6419                         if (!info) {
6420                                 DEBUG(0,("enumprinterdrivers_level1: "
6421                                         "failed to enlarge driver info buffer!\n"));
6422                                 result = WERR_NOMEM;
6423                                 goto out;
6424                         }
6425                 }
6426
6427                 for (i=0; i<ndrivers; i++) {
6428                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6429                         ZERO_STRUCT(driver);
6430                         result = get_a_printer_driver(&driver, 3, list[i],
6431                                                       architecture, version);
6432                         if (!W_ERROR_IS_OK(result)) {
6433                                 goto out;
6434                         }
6435                         result = fill_printer_driver_info1(info, &info[*count+i].info1,
6436                                                            &driver, servername,
6437                                                            architecture);
6438                         if (!W_ERROR_IS_OK(result)) {
6439                                 free_a_printer_driver(driver, 3);
6440                                 goto out;
6441                         }
6442                         free_a_printer_driver(driver, 3);
6443                 }
6444
6445                 *count += ndrivers;
6446                 SAFE_FREE(list);
6447         }
6448
6449  out:
6450         SAFE_FREE(list);
6451
6452         if (!W_ERROR_IS_OK(result)) {
6453                 TALLOC_FREE(info);
6454                 *count = 0;
6455                 return result;
6456         }
6457
6458         *info_p = info;
6459
6460         return WERR_OK;
6461 }
6462
6463 /****************************************************************************
6464  Enumerates all printer drivers at level 2.
6465 ****************************************************************************/
6466
6467 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6468                                         const char *servername,
6469                                         const char *architecture,
6470                                         union spoolss_DriverInfo **info_p,
6471                                         uint32_t *count)
6472 {
6473         int i;
6474         int ndrivers;
6475         uint32_t version;
6476         fstring *list = NULL;
6477         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6478         union spoolss_DriverInfo *info = NULL;
6479         WERROR result = WERR_OK;
6480
6481         *count = 0;
6482
6483         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6484                 list = NULL;
6485                 ndrivers = get_ntdrivers(&list, architecture, version);
6486                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6487                         ndrivers, architecture, version));
6488
6489                 if (ndrivers == -1) {
6490                         result = WERR_NOMEM;
6491                         goto out;
6492                 }
6493
6494                 if (ndrivers != 0) {
6495                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6496                                                     union spoolss_DriverInfo,
6497                                                     *count + ndrivers);
6498                         if (!info) {
6499                                 DEBUG(0,("enumprinterdrivers_level2: "
6500                                         "failed to enlarge driver info buffer!\n"));
6501                                 result = WERR_NOMEM;
6502                                 goto out;
6503                         }
6504                 }
6505
6506                 for (i=0; i<ndrivers; i++) {
6507                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6508                         ZERO_STRUCT(driver);
6509                         result = get_a_printer_driver(&driver, 3, list[i],
6510                                                       architecture, version);
6511                         if (!W_ERROR_IS_OK(result)) {
6512                                 goto out;
6513                         }
6514                         result = fill_printer_driver_info2(info, &info[*count+i].info2,
6515                                                            &driver, servername);
6516                         if (!W_ERROR_IS_OK(result)) {
6517                                 free_a_printer_driver(driver, 3);
6518                                 goto out;
6519                         }
6520                         free_a_printer_driver(driver, 3);
6521                 }
6522
6523                 *count += ndrivers;
6524                 SAFE_FREE(list);
6525         }
6526
6527  out:
6528         SAFE_FREE(list);
6529
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  Enumerates all printer drivers at level 3.
6543 ****************************************************************************/
6544
6545 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6546                                         const char *servername,
6547                                         const char *architecture,
6548                                         union spoolss_DriverInfo **info_p,
6549                                         uint32_t *count)
6550 {
6551         int i;
6552         int ndrivers;
6553         uint32_t version;
6554         fstring *list = NULL;
6555         union spoolss_DriverInfo *info = NULL;
6556         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6557         WERROR result = WERR_OK;
6558
6559         *count = 0;
6560
6561         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6562                 list = NULL;
6563                 ndrivers = get_ntdrivers(&list, architecture, version);
6564                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6565                         ndrivers, architecture, version));
6566
6567                 if (ndrivers == -1) {
6568                         result = WERR_NOMEM;
6569                         goto out;
6570                 }
6571
6572                 if (ndrivers != 0) {
6573                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6574                                                     union spoolss_DriverInfo,
6575                                                     *count + ndrivers);
6576                         if (!info) {
6577                                 DEBUG(0,("enumprinterdrivers_level3: "
6578                                         "failed to enlarge driver info buffer!\n"));
6579                                 result = WERR_NOMEM;
6580                                 goto out;
6581                         }
6582                 }
6583
6584                 for (i=0; i<ndrivers; i++) {
6585                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6586                         ZERO_STRUCT(driver);
6587                         result = get_a_printer_driver(&driver, 3, list[i],
6588                                                       architecture, version);
6589                         if (!W_ERROR_IS_OK(result)) {
6590                                 goto out;
6591                         }
6592                         result = fill_printer_driver_info3(info, &info[*count+i].info3,
6593                                                            &driver, servername);
6594                         if (!W_ERROR_IS_OK(result)) {
6595                                 free_a_printer_driver(driver, 3);
6596                                 goto out;
6597                         }
6598
6599                         free_a_printer_driver(driver, 3);
6600                 }
6601
6602                 *count += ndrivers;
6603                 SAFE_FREE(list);
6604         }
6605
6606  out:
6607         SAFE_FREE(list);
6608
6609         if (!W_ERROR_IS_OK(result)) {
6610                 TALLOC_FREE(info);
6611                 *count = 0;
6612                 return result;
6613         }
6614
6615         *info_p = info;
6616
6617         return WERR_OK;
6618 }
6619
6620 /****************************************************************
6621  _spoolss_EnumPrinterDrivers
6622 ****************************************************************/
6623
6624 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6625                                    struct spoolss_EnumPrinterDrivers *r)
6626 {
6627         const char *cservername;
6628         WERROR result;
6629
6630         /* that's an [in out] buffer */
6631
6632         if (!r->in.buffer && (r->in.offered != 0)) {
6633                 return WERR_INVALID_PARAM;
6634         }
6635
6636         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6637
6638         *r->out.needed = 0;
6639         *r->out.count = 0;
6640         *r->out.info = NULL;
6641
6642         cservername = canon_servername(r->in.server);
6643
6644         if (!is_myname_or_ipaddr(cservername)) {
6645                 return WERR_UNKNOWN_PRINTER_DRIVER;
6646         }
6647
6648         switch (r->in.level) {
6649         case 1:
6650                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6651                                                    r->in.environment,
6652                                                    r->out.info, r->out.count);
6653                 break;
6654         case 2:
6655                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6656                                                    r->in.environment,
6657                                                    r->out.info, r->out.count);
6658                 break;
6659         case 3:
6660                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6661                                                    r->in.environment,
6662                                                    r->out.info, r->out.count);
6663                 break;
6664         default:
6665                 return WERR_UNKNOWN_LEVEL;
6666         }
6667
6668         if (!W_ERROR_IS_OK(result)) {
6669                 return result;
6670         }
6671
6672         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6673                                                      spoolss_EnumPrinterDrivers, NULL,
6674                                                      *r->out.info, r->in.level,
6675                                                      *r->out.count);
6676         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6677         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6678
6679         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6680 }
6681
6682 /****************************************************************************
6683 ****************************************************************************/
6684
6685 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6686                                struct spoolss_FormInfo1 *r,
6687                                const nt_forms_struct *form)
6688 {
6689         r->form_name    = talloc_strdup(mem_ctx, form->name);
6690         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6691
6692         r->flags        = form->flag;
6693         r->size.width   = form->width;
6694         r->size.height  = form->length;
6695         r->area.left    = form->left;
6696         r->area.top     = form->top;
6697         r->area.right   = form->right;
6698         r->area.bottom  = form->bottom;
6699
6700         return WERR_OK;
6701 }
6702
6703 /****************************************************************
6704  spoolss_enumforms_level1
6705 ****************************************************************/
6706
6707 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6708                                        const nt_forms_struct *builtin_forms,
6709                                        uint32_t num_builtin_forms,
6710                                        const nt_forms_struct *user_forms,
6711                                        uint32_t num_user_forms,
6712                                        union spoolss_FormInfo **info_p,
6713                                        uint32_t *count)
6714 {
6715         union spoolss_FormInfo *info;
6716         WERROR result = WERR_OK;
6717         int i;
6718
6719         *count = num_builtin_forms + num_user_forms;
6720
6721         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6722         W_ERROR_HAVE_NO_MEMORY(info);
6723
6724         /* construct the list of form structures */
6725         for (i=0; i<num_builtin_forms; i++) {
6726                 DEBUGADD(6,("Filling form number [%d]\n",i));
6727                 result = fill_form_info_1(info, &info[i].info1,
6728                                           &builtin_forms[i]);
6729                 if (!W_ERROR_IS_OK(result)) {
6730                         goto out;
6731                 }
6732         }
6733
6734         for (; i<num_user_forms; i++) {
6735                 DEBUGADD(6,("Filling form number [%d]\n",i));
6736                 result = fill_form_info_1(info, &info[i].info1,
6737                                           &user_forms[i-num_builtin_forms]);
6738                 if (!W_ERROR_IS_OK(result)) {
6739                         goto out;
6740                 }
6741         }
6742
6743  out:
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  _spoolss_EnumForms
6757 ****************************************************************/
6758
6759 WERROR _spoolss_EnumForms(pipes_struct *p,
6760                           struct spoolss_EnumForms *r)
6761 {
6762         WERROR result;
6763         nt_forms_struct *user_forms = NULL;
6764         nt_forms_struct *builtin_forms = NULL;
6765         uint32_t num_user_forms;
6766         uint32_t num_builtin_forms;
6767
6768         *r->out.count = 0;
6769         *r->out.needed = 0;
6770         *r->out.info = NULL;
6771
6772         /* that's an [in out] buffer */
6773
6774         if (!r->in.buffer && (r->in.offered != 0) ) {
6775                 return WERR_INVALID_PARAM;
6776         }
6777
6778         DEBUG(4,("_spoolss_EnumForms\n"));
6779         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6780         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6781
6782         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6783         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6784         num_user_forms = get_ntforms(&user_forms);
6785         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6786
6787         if (num_user_forms + num_builtin_forms == 0) {
6788                 SAFE_FREE(builtin_forms);
6789                 SAFE_FREE(user_forms);
6790                 return WERR_NO_MORE_ITEMS;
6791         }
6792
6793         switch (r->in.level) {
6794         case 1:
6795                 result = spoolss_enumforms_level1(p->mem_ctx,
6796                                                   builtin_forms,
6797                                                   num_builtin_forms,
6798                                                   user_forms,
6799                                                   num_user_forms,
6800                                                   r->out.info,
6801                                                   r->out.count);
6802                 break;
6803         default:
6804                 result = WERR_UNKNOWN_LEVEL;
6805                 break;
6806         }
6807
6808         SAFE_FREE(user_forms);
6809         SAFE_FREE(builtin_forms);
6810
6811         if (!W_ERROR_IS_OK(result)) {
6812                 return result;
6813         }
6814
6815         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6816                                                      spoolss_EnumForms, NULL,
6817                                                      *r->out.info, r->in.level,
6818                                                      *r->out.count);
6819         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6820         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6821
6822         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6823 }
6824
6825 /****************************************************************
6826 ****************************************************************/
6827
6828 static WERROR find_form_byname(const char *name,
6829                                nt_forms_struct *form)
6830 {
6831         nt_forms_struct *list = NULL;
6832         int num_forms = 0, i = 0;
6833
6834         if (get_a_builtin_ntform_by_string(name, form)) {
6835                 return WERR_OK;
6836         }
6837
6838         num_forms = get_ntforms(&list);
6839         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6840
6841         if (num_forms == 0) {
6842                 return WERR_BADFID;
6843         }
6844
6845         /* Check if the requested name is in the list of form structures */
6846         for (i = 0; i < num_forms; i++) {
6847
6848                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6849
6850                 if (strequal(name, list[i].name)) {
6851                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6852                         *form = list[i];
6853                         SAFE_FREE(list);
6854                         return WERR_OK;
6855                 }
6856         }
6857
6858         SAFE_FREE(list);
6859
6860         return WERR_BADFID;
6861 }
6862
6863 /****************************************************************
6864  _spoolss_GetForm
6865 ****************************************************************/
6866
6867 WERROR _spoolss_GetForm(pipes_struct *p,
6868                         struct spoolss_GetForm *r)
6869 {
6870         WERROR result;
6871         nt_forms_struct form;
6872
6873         /* that's an [in out] buffer */
6874
6875         if (!r->in.buffer && (r->in.offered != 0)) {
6876                 return WERR_INVALID_PARAM;
6877         }
6878
6879         DEBUG(4,("_spoolss_GetForm\n"));
6880         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6881         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6882
6883         result = find_form_byname(r->in.form_name, &form);
6884         if (!W_ERROR_IS_OK(result)) {
6885                 TALLOC_FREE(r->out.info);
6886                 return result;
6887         }
6888
6889         switch (r->in.level) {
6890         case 1:
6891                 result = fill_form_info_1(p->mem_ctx,
6892                                           &r->out.info->info1,
6893                                           &form);
6894                 break;
6895
6896         default:
6897                 result = WERR_UNKNOWN_LEVEL;
6898                 break;
6899         }
6900
6901         if (!W_ERROR_IS_OK(result)) {
6902                 TALLOC_FREE(r->out.info);
6903                 return result;
6904         }
6905
6906         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6907                                                r->out.info, r->in.level);
6908         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6909
6910         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6911 }
6912
6913 /****************************************************************************
6914 ****************************************************************************/
6915
6916 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6917                           struct spoolss_PortInfo1 *r,
6918                           const char *name)
6919 {
6920         r->port_name = talloc_strdup(mem_ctx, name);
6921         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6922
6923         return WERR_OK;
6924 }
6925
6926 /****************************************************************************
6927  TODO: This probably needs distinguish between TCP/IP and Local ports
6928  somehow.
6929 ****************************************************************************/
6930
6931 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6932                           struct spoolss_PortInfo2 *r,
6933                           const char *name)
6934 {
6935         r->port_name = talloc_strdup(mem_ctx, name);
6936         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6937
6938         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6939         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6940
6941         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
6942         W_ERROR_HAVE_NO_MEMORY(r->description);
6943
6944         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6945         r->reserved = 0;
6946
6947         return WERR_OK;
6948 }
6949
6950
6951 /****************************************************************************
6952  wrapper around the enumer ports command
6953 ****************************************************************************/
6954
6955 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
6956 {
6957         char *cmd = lp_enumports_cmd();
6958         char **qlines = NULL;
6959         char *command = NULL;
6960         int numlines;
6961         int ret;
6962         int fd;
6963
6964         *count = 0;
6965         *lines = NULL;
6966
6967         /* if no hook then just fill in the default port */
6968
6969         if ( !*cmd ) {
6970                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6971                         return WERR_NOMEM;
6972                 }
6973                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6974                         TALLOC_FREE(qlines);
6975                         return WERR_NOMEM;
6976                 }
6977                 qlines[1] = NULL;
6978                 numlines = 1;
6979         }
6980         else {
6981                 /* we have a valid enumport command */
6982
6983                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6984                 if (!command) {
6985                         return WERR_NOMEM;
6986                 }
6987
6988                 DEBUG(10,("Running [%s]\n", command));
6989                 ret = smbrun(command, &fd);
6990                 DEBUG(10,("Returned [%d]\n", ret));
6991                 TALLOC_FREE(command);
6992                 if (ret != 0) {
6993                         if (fd != -1) {
6994                                 close(fd);
6995                         }
6996                         return WERR_ACCESS_DENIED;
6997                 }
6998
6999                 numlines = 0;
7000                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7001                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7002                 close(fd);
7003         }
7004
7005         *count = numlines;
7006         *lines = qlines;
7007
7008         return WERR_OK;
7009 }
7010
7011 /****************************************************************************
7012  enumports level 1.
7013 ****************************************************************************/
7014
7015 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7016                                 union spoolss_PortInfo **info_p,
7017                                 uint32_t *count)
7018 {
7019         union spoolss_PortInfo *info = NULL;
7020         int i=0;
7021         WERROR result = WERR_OK;
7022         char **qlines = NULL;
7023         int numlines = 0;
7024
7025         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7026         if (!W_ERROR_IS_OK(result)) {
7027                 goto out;
7028         }
7029
7030         if (numlines) {
7031                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7032                 if (!info) {
7033                         DEBUG(10,("Returning WERR_NOMEM\n"));
7034                         result = WERR_NOMEM;
7035                         goto out;
7036                 }
7037
7038                 for (i=0; i<numlines; i++) {
7039                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7040                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7041                         if (!W_ERROR_IS_OK(result)) {
7042                                 goto out;
7043                         }
7044                 }
7045         }
7046         TALLOC_FREE(qlines);
7047
7048 out:
7049         if (!W_ERROR_IS_OK(result)) {
7050                 TALLOC_FREE(info);
7051                 TALLOC_FREE(qlines);
7052                 *count = 0;
7053                 *info_p = NULL;
7054                 return result;
7055         }
7056
7057         *info_p = info;
7058         *count = numlines;
7059
7060         return WERR_OK;
7061 }
7062
7063 /****************************************************************************
7064  enumports level 2.
7065 ****************************************************************************/
7066
7067 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7068                                 union spoolss_PortInfo **info_p,
7069                                 uint32_t *count)
7070 {
7071         union spoolss_PortInfo *info = NULL;
7072         int i=0;
7073         WERROR result = WERR_OK;
7074         char **qlines = NULL;
7075         int numlines = 0;
7076
7077         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7078         if (!W_ERROR_IS_OK(result)) {
7079                 goto out;
7080         }
7081
7082         if (numlines) {
7083                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7084                 if (!info) {
7085                         DEBUG(10,("Returning WERR_NOMEM\n"));
7086                         result = WERR_NOMEM;
7087                         goto out;
7088                 }
7089
7090                 for (i=0; i<numlines; i++) {
7091                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7092                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7093                         if (!W_ERROR_IS_OK(result)) {
7094                                 goto out;
7095                         }
7096                 }
7097         }
7098         TALLOC_FREE(qlines);
7099
7100 out:
7101         if (!W_ERROR_IS_OK(result)) {
7102                 TALLOC_FREE(info);
7103                 TALLOC_FREE(qlines);
7104                 *count = 0;
7105                 *info_p = NULL;
7106                 return result;
7107         }
7108
7109         *info_p = info;
7110         *count = numlines;
7111
7112         return WERR_OK;
7113 }
7114
7115 /****************************************************************
7116  _spoolss_EnumPorts
7117 ****************************************************************/
7118
7119 WERROR _spoolss_EnumPorts(pipes_struct *p,
7120                           struct spoolss_EnumPorts *r)
7121 {
7122         WERROR result;
7123
7124         /* that's an [in out] buffer */
7125
7126         if (!r->in.buffer && (r->in.offered != 0)) {
7127                 return WERR_INVALID_PARAM;
7128         }
7129
7130         DEBUG(4,("_spoolss_EnumPorts\n"));
7131
7132         *r->out.count = 0;
7133         *r->out.needed = 0;
7134         *r->out.info = NULL;
7135
7136         switch (r->in.level) {
7137         case 1:
7138                 result = enumports_level_1(p->mem_ctx, r->out.info,
7139                                            r->out.count);
7140                 break;
7141         case 2:
7142                 result = enumports_level_2(p->mem_ctx, r->out.info,
7143                                            r->out.count);
7144                 break;
7145         default:
7146                 return WERR_UNKNOWN_LEVEL;
7147         }
7148
7149         if (!W_ERROR_IS_OK(result)) {
7150                 return result;
7151         }
7152
7153         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7154                                                      spoolss_EnumPorts, NULL,
7155                                                      *r->out.info, r->in.level,
7156                                                      *r->out.count);
7157         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7158         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7159
7160         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7161 }
7162
7163 /****************************************************************************
7164 ****************************************************************************/
7165
7166 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7167                                            const char *server,
7168                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7169                                            struct spoolss_DeviceMode *devmode,
7170                                            struct security_descriptor *sec_desc,
7171                                            struct spoolss_UserLevelCtr *user_ctr,
7172                                            POLICY_HND *handle)
7173 {
7174         NT_PRINTER_INFO_LEVEL *printer = NULL;
7175         fstring name;
7176         int     snum;
7177         WERROR err = WERR_OK;
7178
7179         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7180                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7181                 return WERR_NOMEM;
7182         }
7183
7184         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7185         if (!convert_printer_info(info_ctr, printer)) {
7186                 free_a_printer(&printer, 2);
7187                 return WERR_NOMEM;
7188         }
7189
7190         /* check to see if the printer already exists */
7191
7192         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7193                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7194                         printer->info_2->sharename));
7195                 free_a_printer(&printer, 2);
7196                 return WERR_PRINTER_ALREADY_EXISTS;
7197         }
7198
7199         /* FIXME!!!  smbd should check to see if the driver is installed before
7200            trying to add a printer like this  --jerry */
7201
7202         if (*lp_addprinter_cmd() ) {
7203                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7204                                        printer) ) {
7205                         free_a_printer(&printer,2);
7206                         return WERR_ACCESS_DENIED;
7207                 }
7208         } else {
7209                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7210                         "smb.conf parameter \"addprinter command\" is defined. This"
7211                         "parameter must exist for this call to succeed\n",
7212                         printer->info_2->sharename ));
7213         }
7214
7215         /* use our primary netbios name since get_a_printer() will convert
7216            it to what the client expects on a case by case basis */
7217
7218         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7219              printer->info_2->sharename);
7220
7221
7222         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7223                 free_a_printer(&printer,2);
7224                 return WERR_ACCESS_DENIED;
7225         }
7226
7227         /* you must be a printer admin to add a new printer */
7228         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7229                 free_a_printer(&printer,2);
7230                 return WERR_ACCESS_DENIED;
7231         }
7232
7233         /*
7234          * Do sanity check on the requested changes for Samba.
7235          */
7236
7237         if (!check_printer_ok(printer->info_2, snum)) {
7238                 free_a_printer(&printer,2);
7239                 return WERR_INVALID_PARAM;
7240         }
7241
7242         /*
7243          * When a printer is created, the drivername bound to the printer is used
7244          * to lookup previously saved driver initialization info, which is then
7245          * bound to the new printer, simulating what happens in the Windows arch.
7246          */
7247
7248         if (!devmode)
7249         {
7250                 set_driver_init(printer, 2);
7251         }
7252         else
7253         {
7254                 /* A valid devmode was included, convert and link it
7255                 */
7256                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7257
7258                 if (!convert_devicemode(printer->info_2->printername, devmode,
7259                                         &printer->info_2->devmode)) {
7260                         return  WERR_NOMEM;
7261                 }
7262         }
7263
7264         /* write the ASCII on disk */
7265         err = mod_a_printer(printer, 2);
7266         if (!W_ERROR_IS_OK(err)) {
7267                 free_a_printer(&printer,2);
7268                 return err;
7269         }
7270
7271         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7272                 /* Handle open failed - remove addition. */
7273                 del_a_printer(printer->info_2->sharename);
7274                 free_a_printer(&printer,2);
7275                 ZERO_STRUCTP(handle);
7276                 return WERR_ACCESS_DENIED;
7277         }
7278
7279         update_c_setprinter(False);
7280         free_a_printer(&printer,2);
7281
7282         return WERR_OK;
7283 }
7284
7285 /****************************************************************
7286  _spoolss_AddPrinterEx
7287 ****************************************************************/
7288
7289 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7290                              struct spoolss_AddPrinterEx *r)
7291 {
7292         switch (r->in.info_ctr->level) {
7293         case 1:
7294                 /* we don't handle yet */
7295                 /* but I know what to do ... */
7296                 return WERR_UNKNOWN_LEVEL;
7297         case 2:
7298                 return spoolss_addprinterex_level_2(p, r->in.server,
7299                                                     r->in.info_ctr,
7300                                                     r->in.devmode_ctr->devmode,
7301                                                     r->in.secdesc_ctr->sd,
7302                                                     r->in.userlevel_ctr,
7303                                                     r->out.handle);
7304         default:
7305                 return WERR_UNKNOWN_LEVEL;
7306         }
7307 }
7308
7309 /****************************************************************
7310  _spoolss_AddPrinterDriver
7311 ****************************************************************/
7312
7313 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7314                                  struct spoolss_AddPrinterDriver *r)
7315 {
7316         uint32_t level = r->in.info_ctr->level;
7317         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7318         WERROR err = WERR_OK;
7319         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7320         fstring driver_name;
7321         uint32 version;
7322         const char *fn;
7323
7324         switch (p->hdr_req.opnum) {
7325                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7326                         fn = "_spoolss_AddPrinterDriver";
7327                         break;
7328                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7329                         fn = "_spoolss_AddPrinterDriverEx";
7330                         break;
7331                 default:
7332                         return WERR_INVALID_PARAM;
7333         }
7334
7335
7336         /* FIXME */
7337         if (level != 3 && level != 6) {
7338                 /* Clever hack from Martin Zielinski <mz@seh.de>
7339                  * to allow downgrade from level 8 (Vista).
7340                  */
7341                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7342                 return WERR_UNKNOWN_LEVEL;
7343         }
7344
7345         ZERO_STRUCT(driver);
7346
7347         if (!convert_printer_driver_info(info, &driver, level)) {
7348                 err = WERR_NOMEM;
7349                 goto done;
7350         }
7351
7352         DEBUG(5,("Cleaning driver's information\n"));
7353         err = clean_up_driver_struct(p, driver, level);
7354         if (!W_ERROR_IS_OK(err))
7355                 goto done;
7356
7357         DEBUG(5,("Moving driver to final destination\n"));
7358         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7359                                                               &err)) ) {
7360                 goto done;
7361         }
7362
7363         if (add_a_printer_driver(driver, level)!=0) {
7364                 err = WERR_ACCESS_DENIED;
7365                 goto done;
7366         }
7367
7368         switch(level) {
7369         case 3:
7370                 fstrcpy(driver_name,
7371                         driver.info_3->name ? driver.info_3->name : "");
7372                 break;
7373         case 6:
7374                 fstrcpy(driver_name,
7375                         driver.info_6->name ?  driver.info_6->name : "");
7376                 break;
7377         }
7378
7379         /*
7380          * I think this is where he DrvUpgradePrinter() hook would be
7381          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7382          * server.  Right now, we just need to send ourselves a message
7383          * to update each printer bound to this driver.   --jerry
7384          */
7385
7386         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7387                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7388                         fn, driver_name));
7389         }
7390
7391         /*
7392          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7393          * decide if the driver init data should be deleted. The rules are:
7394          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7395          *  2) delete init data only if there is no 2k/Xp driver
7396          *  3) always delete init data
7397          * The generalized rule is always use init data from the highest order driver.
7398          * It is necessary to follow the driver install by an initialization step to
7399          * finish off this process.
7400         */
7401         if (level == 3)
7402                 version = driver.info_3->cversion;
7403         else if (level == 6)
7404                 version = driver.info_6->version;
7405         else
7406                 version = -1;
7407         switch (version) {
7408                 /*
7409                  * 9x printer driver - never delete init data
7410                 */
7411                 case 0:
7412                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7413                                 fn, driver_name));
7414                         break;
7415
7416                 /*
7417                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7418                  * there is no 2k/Xp driver init data for this driver name.
7419                 */
7420                 case 2:
7421                 {
7422                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7423
7424                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7425                                 /*
7426                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7427                                 */
7428                                 if (!del_driver_init(driver_name))
7429                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7430                                                 fn, driver_name));
7431                         } else {
7432                                 /*
7433                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7434                                 */
7435                                 free_a_printer_driver(driver1,3);
7436                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7437                                         fn, driver_name));
7438                         }
7439                 }
7440                 break;
7441
7442                 /*
7443                  * 2k or Xp printer driver - always delete init data
7444                 */
7445                 case 3:
7446                         if (!del_driver_init(driver_name))
7447                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7448                                         fn, driver_name));
7449                         break;
7450
7451                 default:
7452                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7453                         break;
7454         }
7455
7456
7457 done:
7458         free_a_printer_driver(driver, level);
7459         return err;
7460 }
7461
7462 /****************************************************************
7463  _spoolss_AddPrinterDriverEx
7464 ****************************************************************/
7465
7466 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7467                                    struct spoolss_AddPrinterDriverEx *r)
7468 {
7469         struct spoolss_AddPrinterDriver a;
7470
7471         /*
7472          * we only support the semantics of AddPrinterDriver()
7473          * i.e. only copy files that are newer than existing ones
7474          */
7475
7476         if (r->in.flags != APD_COPY_NEW_FILES) {
7477                 return WERR_ACCESS_DENIED;
7478         }
7479
7480         a.in.servername         = r->in.servername;
7481         a.in.info_ctr           = r->in.info_ctr;
7482
7483         return _spoolss_AddPrinterDriver(p, &a);
7484 }
7485
7486 /****************************************************************************
7487 ****************************************************************************/
7488
7489 struct _spoolss_paths {
7490         int type;
7491         const char *share;
7492         const char *dir;
7493 };
7494
7495 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7496
7497 static const struct _spoolss_paths spoolss_paths[]= {
7498         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7499         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7500 };
7501
7502 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7503                                           const char *servername,
7504                                           const char *environment,
7505                                           int component,
7506                                           char **path)
7507 {
7508         const char *pservername = NULL;
7509         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7510         const char *short_archi;
7511
7512         *path = NULL;
7513
7514         /* environment may be empty */
7515         if (environment && strlen(environment)) {
7516                 long_archi = environment;
7517         }
7518
7519         /* servername may be empty */
7520         if (servername && strlen(servername)) {
7521                 pservername = canon_servername(servername);
7522
7523                 if (!is_myname_or_ipaddr(pservername)) {
7524                         return WERR_INVALID_PARAM;
7525                 }
7526         }
7527
7528         if (!(short_archi = get_short_archi(long_archi))) {
7529                 return WERR_INVALID_ENVIRONMENT;
7530         }
7531
7532         switch (component) {
7533         case SPOOLSS_PRTPROCS_PATH:
7534         case SPOOLSS_DRIVER_PATH:
7535                 if (pservername) {
7536                         *path = talloc_asprintf(mem_ctx,
7537                                         "\\\\%s\\%s\\%s",
7538                                         pservername,
7539                                         spoolss_paths[component].share,
7540                                         short_archi);
7541                 } else {
7542                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7543                                         SPOOLSS_DEFAULT_SERVER_PATH,
7544                                         spoolss_paths[component].dir,
7545                                         short_archi);
7546                 }
7547                 break;
7548         default:
7549                 return WERR_INVALID_PARAM;
7550         }
7551
7552         if (!*path) {
7553                 return WERR_NOMEM;
7554         }
7555
7556         return WERR_OK;
7557 }
7558
7559 /****************************************************************************
7560 ****************************************************************************/
7561
7562 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7563                                           const char *servername,
7564                                           const char *environment,
7565                                           struct spoolss_DriverDirectoryInfo1 *r)
7566 {
7567         WERROR werr;
7568         char *path = NULL;
7569
7570         werr = compose_spoolss_server_path(mem_ctx,
7571                                            servername,
7572                                            environment,
7573                                            SPOOLSS_DRIVER_PATH,
7574                                            &path);
7575         if (!W_ERROR_IS_OK(werr)) {
7576                 return werr;
7577         }
7578
7579         DEBUG(4,("printer driver directory: [%s]\n", path));
7580
7581         r->directory_name = path;
7582
7583         return WERR_OK;
7584 }
7585
7586 /****************************************************************
7587  _spoolss_GetPrinterDriverDirectory
7588 ****************************************************************/
7589
7590 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7591                                           struct spoolss_GetPrinterDriverDirectory *r)
7592 {
7593         WERROR werror;
7594
7595         /* that's an [in out] buffer */
7596
7597         if (!r->in.buffer && (r->in.offered != 0)) {
7598                 return WERR_INVALID_PARAM;
7599         }
7600
7601         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7602                 r->in.level));
7603
7604         *r->out.needed = 0;
7605
7606         /* r->in.level is ignored */
7607
7608         werror = getprinterdriverdir_level_1(p->mem_ctx,
7609                                              r->in.server,
7610                                              r->in.environment,
7611                                              &r->out.info->info1);
7612         if (!W_ERROR_IS_OK(werror)) {
7613                 TALLOC_FREE(r->out.info);
7614                 return werror;
7615         }
7616
7617         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7618                                                r->out.info, r->in.level);
7619         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7620
7621         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7622 }
7623
7624 /****************************************************************
7625  _spoolss_EnumPrinterData
7626 ****************************************************************/
7627
7628 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7629                                 struct spoolss_EnumPrinterData *r)
7630 {
7631         NT_PRINTER_INFO_LEVEL *printer = NULL;
7632         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7633         int             snum;
7634         WERROR          result;
7635         REGISTRY_VALUE  *val = NULL;
7636         NT_PRINTER_DATA *p_data;
7637         int             i, key_index, num_values;
7638         int             name_length;
7639
7640         *r->out.value_needed    = 0;
7641         *r->out.type            = REG_NONE;
7642         *r->out.data_needed     = 0;
7643
7644         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7645
7646         if (!Printer) {
7647                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7648                         OUR_HANDLE(r->in.handle)));
7649                 return WERR_BADFID;
7650         }
7651
7652         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7653                 return WERR_BADFID;
7654         }
7655
7656         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7657         if (!W_ERROR_IS_OK(result)) {
7658                 return result;
7659         }
7660
7661         p_data = printer->info_2->data;
7662         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7663
7664         result = WERR_OK;
7665
7666         /*
7667          * The NT machine wants to know the biggest size of value and data
7668          *
7669          * cf: MSDN EnumPrinterData remark section
7670          */
7671
7672         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7673
7674                 uint32_t biggest_valuesize = 0;
7675                 uint32_t biggest_datasize = 0;
7676
7677                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7678
7679                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7680
7681                 for ( i=0; i<num_values; i++ )
7682                 {
7683                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7684
7685                         name_length = strlen(val->valuename);
7686                         if ( strlen(val->valuename) > biggest_valuesize )
7687                                 biggest_valuesize = name_length;
7688
7689                         if ( val->size > biggest_datasize )
7690                                 biggest_datasize = val->size;
7691
7692                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7693                                 biggest_datasize));
7694                 }
7695
7696                 /* the value is an UNICODE string but real_value_size is the length
7697                    in bytes including the trailing 0 */
7698
7699                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7700                 *r->out.data_needed  = biggest_datasize;
7701
7702                 DEBUG(6,("final values: [%d], [%d]\n",
7703                         *r->out.value_needed, *r->out.data_needed));
7704
7705                 goto done;
7706         }
7707
7708         /*
7709          * the value len is wrong in NT sp3
7710          * that's the number of bytes not the number of unicode chars
7711          */
7712
7713         if (key_index != -1) {
7714                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7715                                                 r->in.enum_index);
7716         }
7717
7718         if (!val) {
7719
7720                 /* out_value should default to "" or else NT4 has
7721                    problems unmarshalling the response */
7722
7723                 if (r->in.value_offered) {
7724                         *r->out.value_needed = 1;
7725                         r->out.value_name = talloc_strdup(r, "");
7726                         if (!r->out.value_name) {
7727                                 result = WERR_NOMEM;
7728                                 goto done;
7729                         }
7730                 } else {
7731                         r->out.value_name = NULL;
7732                         *r->out.value_needed = 0;
7733                 }
7734
7735                 /* the data is counted in bytes */
7736
7737                 *r->out.data_needed = r->in.data_offered;
7738
7739                 result = WERR_NO_MORE_ITEMS;
7740         } else {
7741                 /*
7742                  * the value is:
7743                  * - counted in bytes in the request
7744                  * - counted in UNICODE chars in the max reply
7745                  * - counted in bytes in the real size
7746                  *
7747                  * take a pause *before* coding not *during* coding
7748                  */
7749
7750                 /* name */
7751                 if (r->in.value_offered) {
7752                         r->out.value_name = talloc_strdup(r, regval_name(val));
7753                         if (!r->out.value_name) {
7754                                 result = WERR_NOMEM;
7755                                 goto done;
7756                         }
7757                         *r->out.value_needed = strlen_m(regval_name(val));
7758                 } else {
7759                         r->out.value_name = NULL;
7760                         *r->out.value_needed = 0;
7761                 }
7762
7763                 /* type */
7764
7765                 *r->out.type = regval_type(val);
7766
7767                 /* data - counted in bytes */
7768
7769                 if (r->out.data && regval_size(val)) {
7770                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
7771                 }
7772
7773                 *r->out.data_needed = regval_size(val);
7774         }
7775
7776 done:
7777         free_a_printer(&printer, 2);
7778         return result;
7779 }
7780
7781 /****************************************************************
7782  _spoolss_SetPrinterData
7783 ****************************************************************/
7784
7785 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7786                                struct spoolss_SetPrinterData *r)
7787 {
7788         NT_PRINTER_INFO_LEVEL *printer = NULL;
7789         int snum=0;
7790         WERROR result = WERR_OK;
7791         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7792         DATA_BLOB blob;
7793
7794         DEBUG(5,("_spoolss_SetPrinterData\n"));
7795
7796         if (!Printer) {
7797                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7798                         OUR_HANDLE(r->in.handle)));
7799                 return WERR_BADFID;
7800         }
7801
7802         if (Printer->printer_type == SPLHND_SERVER) {
7803                 DEBUG(10,("_spoolss_SetPrinterData: "
7804                         "Not implemented for server handles yet\n"));
7805                 return WERR_INVALID_PARAM;
7806         }
7807
7808         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7809                 return WERR_BADFID;
7810         }
7811
7812         /*
7813          * Access check : NT returns "access denied" if you make a
7814          * SetPrinterData call without the necessary privildge.
7815          * we were originally returning OK if nothing changed
7816          * which made Win2k issue **a lot** of SetPrinterData
7817          * when connecting to a printer  --jerry
7818          */
7819
7820         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7821                 DEBUG(3,("_spoolss_SetPrinterData: "
7822                         "change denied by handle access permissions\n"));
7823                 result = WERR_ACCESS_DENIED;
7824                 goto done;
7825         }
7826
7827         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7828         if (!W_ERROR_IS_OK(result)) {
7829                 return result;
7830         }
7831
7832         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
7833                                           r->in.type, &r->in.data);
7834         if (!W_ERROR_IS_OK(result)) {
7835                 goto done;
7836         }
7837
7838         /*
7839          * When client side code sets a magic printer data key, detect it and save
7840          * the current printer data and the magic key's data (its the DEVMODE) for
7841          * future printer/driver initializations.
7842          */
7843         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
7844                 /* Set devmode and printer initialization info */
7845                 result = save_driver_init(printer, 2, blob.data, blob.length);
7846
7847                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
7848
7849                 goto done;
7850         }
7851
7852         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
7853                                     r->in.value_name, r->in.type,
7854                                     blob.data, blob.length);
7855         if (W_ERROR_IS_OK(result)) {
7856                 result = mod_a_printer(printer, 2);
7857         }
7858
7859 done:
7860         free_a_printer(&printer, 2);
7861
7862         return result;
7863 }
7864
7865 /****************************************************************
7866  _spoolss_ResetPrinter
7867 ****************************************************************/
7868
7869 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7870                              struct spoolss_ResetPrinter *r)
7871 {
7872         POLICY_HND      *handle = r->in.handle;
7873         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
7874         int             snum;
7875
7876         DEBUG(5,("_spoolss_ResetPrinter\n"));
7877
7878         /*
7879          * All we do is to check to see if the handle and queue is valid.
7880          * This call really doesn't mean anything to us because we only
7881          * support RAW printing.   --jerry
7882          */
7883
7884         if (!Printer) {
7885                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7886                         OUR_HANDLE(handle)));
7887                 return WERR_BADFID;
7888         }
7889
7890         if (!get_printer_snum(p,handle, &snum, NULL))
7891                 return WERR_BADFID;
7892
7893
7894         /* blindly return success */
7895         return WERR_OK;
7896 }
7897
7898 /****************************************************************
7899  _spoolss_DeletePrinterData
7900 ****************************************************************/
7901
7902 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7903                                   struct spoolss_DeletePrinterData *r)
7904 {
7905         POLICY_HND      *handle = r->in.handle;
7906         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7907         int             snum=0;
7908         WERROR          status = WERR_OK;
7909         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
7910
7911         DEBUG(5,("_spoolss_DeletePrinterData\n"));
7912
7913         if (!Printer) {
7914                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7915                         OUR_HANDLE(handle)));
7916                 return WERR_BADFID;
7917         }
7918
7919         if (!get_printer_snum(p, handle, &snum, NULL))
7920                 return WERR_BADFID;
7921
7922         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7923                 DEBUG(3, ("_spoolss_DeletePrinterData: "
7924                         "printer properties change denied by handle\n"));
7925                 return WERR_ACCESS_DENIED;
7926         }
7927
7928         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7929         if (!W_ERROR_IS_OK(status))
7930                 return status;
7931
7932         if (!r->in.value_name) {
7933                 free_a_printer(&printer, 2);
7934                 return WERR_NOMEM;
7935         }
7936
7937         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
7938                                         r->in.value_name );
7939
7940         if ( W_ERROR_IS_OK(status) )
7941                 mod_a_printer( printer, 2 );
7942
7943         free_a_printer(&printer, 2);
7944
7945         return status;
7946 }
7947
7948 /****************************************************************
7949  _spoolss_AddForm
7950 ****************************************************************/
7951
7952 WERROR _spoolss_AddForm(pipes_struct *p,
7953                         struct spoolss_AddForm *r)
7954 {
7955         POLICY_HND *handle = r->in.handle;
7956         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7957         nt_forms_struct tmpForm;
7958         int snum;
7959         WERROR status = WERR_OK;
7960         NT_PRINTER_INFO_LEVEL *printer = NULL;
7961
7962         int count=0;
7963         nt_forms_struct *list=NULL;
7964         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7965
7966         DEBUG(5,("_spoolss_AddForm\n"));
7967
7968         if (!Printer) {
7969                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7970                         OUR_HANDLE(handle)));
7971                 return WERR_BADFID;
7972         }
7973
7974
7975         /* forms can be added on printer of on the print server handle */
7976
7977         if ( Printer->printer_type == SPLHND_PRINTER )
7978         {
7979                 if (!get_printer_snum(p,handle, &snum, NULL))
7980                         return WERR_BADFID;
7981
7982                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7983                 if (!W_ERROR_IS_OK(status))
7984                         goto done;
7985         }
7986
7987         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7988                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7989                 status = WERR_ACCESS_DENIED;
7990                 goto done;
7991         }
7992
7993         /* can't add if builtin */
7994
7995         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7996                 status = WERR_FILE_EXISTS;
7997                 goto done;
7998         }
7999
8000         count = get_ntforms(&list);
8001
8002         if(!add_a_form(&list, form, &count)) {
8003                 status =  WERR_NOMEM;
8004                 goto done;
8005         }
8006
8007         write_ntforms(&list, count);
8008
8009         /*
8010          * ChangeID must always be set if this is a printer
8011          */
8012
8013         if ( Printer->printer_type == SPLHND_PRINTER )
8014                 status = mod_a_printer(printer, 2);
8015
8016 done:
8017         if ( printer )
8018                 free_a_printer(&printer, 2);
8019         SAFE_FREE(list);
8020
8021         return status;
8022 }
8023
8024 /****************************************************************
8025  _spoolss_DeleteForm
8026 ****************************************************************/
8027
8028 WERROR _spoolss_DeleteForm(pipes_struct *p,
8029                            struct spoolss_DeleteForm *r)
8030 {
8031         POLICY_HND *handle = r->in.handle;
8032         const char *form_name = r->in.form_name;
8033         nt_forms_struct tmpForm;
8034         int count=0;
8035         nt_forms_struct *list=NULL;
8036         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8037         int snum;
8038         WERROR status = WERR_OK;
8039         NT_PRINTER_INFO_LEVEL *printer = NULL;
8040
8041         DEBUG(5,("_spoolss_DeleteForm\n"));
8042
8043         if (!Printer) {
8044                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8045                         OUR_HANDLE(handle)));
8046                 return WERR_BADFID;
8047         }
8048
8049         /* forms can be deleted on printer of on the print server handle */
8050
8051         if ( Printer->printer_type == SPLHND_PRINTER )
8052         {
8053                 if (!get_printer_snum(p,handle, &snum, NULL))
8054                         return WERR_BADFID;
8055
8056                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8057                 if (!W_ERROR_IS_OK(status))
8058                         goto done;
8059         }
8060
8061         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8062                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8063                 status = WERR_ACCESS_DENIED;
8064                 goto done;
8065         }
8066
8067         /* can't delete if builtin */
8068
8069         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8070                 status = WERR_INVALID_PARAM;
8071                 goto done;
8072         }
8073
8074         count = get_ntforms(&list);
8075
8076         if ( !delete_a_form(&list, form_name, &count, &status ))
8077                 goto done;
8078
8079         /*
8080          * ChangeID must always be set if this is a printer
8081          */
8082
8083         if ( Printer->printer_type == SPLHND_PRINTER )
8084                 status = mod_a_printer(printer, 2);
8085
8086 done:
8087         if ( printer )
8088                 free_a_printer(&printer, 2);
8089         SAFE_FREE(list);
8090
8091         return status;
8092 }
8093
8094 /****************************************************************
8095  _spoolss_SetForm
8096 ****************************************************************/
8097
8098 WERROR _spoolss_SetForm(pipes_struct *p,
8099                         struct spoolss_SetForm *r)
8100 {
8101         POLICY_HND *handle = r->in.handle;
8102         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8103         nt_forms_struct tmpForm;
8104         int snum;
8105         WERROR status = WERR_OK;
8106         NT_PRINTER_INFO_LEVEL *printer = NULL;
8107
8108         int count=0;
8109         nt_forms_struct *list=NULL;
8110         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8111
8112         DEBUG(5,("_spoolss_SetForm\n"));
8113
8114         if (!Printer) {
8115                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8116                         OUR_HANDLE(handle)));
8117                 return WERR_BADFID;
8118         }
8119
8120         /* forms can be modified on printer of on the print server handle */
8121
8122         if ( Printer->printer_type == SPLHND_PRINTER )
8123         {
8124                 if (!get_printer_snum(p,handle, &snum, NULL))
8125                         return WERR_BADFID;
8126
8127                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8128                 if (!W_ERROR_IS_OK(status))
8129                         goto done;
8130         }
8131
8132         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8133                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8134                 status = WERR_ACCESS_DENIED;
8135                 goto done;
8136         }
8137
8138         /* can't set if builtin */
8139         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8140                 status = WERR_INVALID_PARAM;
8141                 goto done;
8142         }
8143
8144         count = get_ntforms(&list);
8145         update_a_form(&list, form, count);
8146         write_ntforms(&list, count);
8147
8148         /*
8149          * ChangeID must always be set if this is a printer
8150          */
8151
8152         if ( Printer->printer_type == SPLHND_PRINTER )
8153                 status = mod_a_printer(printer, 2);
8154
8155
8156 done:
8157         if ( printer )
8158                 free_a_printer(&printer, 2);
8159         SAFE_FREE(list);
8160
8161         return status;
8162 }
8163
8164 /****************************************************************************
8165  fill_print_processor1
8166 ****************************************************************************/
8167
8168 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8169                                     struct spoolss_PrintProcessorInfo1 *r,
8170                                     const char *print_processor_name)
8171 {
8172         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8173         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8174
8175         return WERR_OK;
8176 }
8177
8178 /****************************************************************************
8179  enumprintprocessors level 1.
8180 ****************************************************************************/
8181
8182 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8183                                           union spoolss_PrintProcessorInfo **info_p,
8184                                           uint32_t *count)
8185 {
8186         union spoolss_PrintProcessorInfo *info;
8187         WERROR result;
8188
8189         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8190         W_ERROR_HAVE_NO_MEMORY(info);
8191
8192         *count = 1;
8193
8194         result = fill_print_processor1(info, &info[0].info1, "winprint");
8195         if (!W_ERROR_IS_OK(result)) {
8196                 goto out;
8197         }
8198
8199  out:
8200         if (!W_ERROR_IS_OK(result)) {
8201                 TALLOC_FREE(info);
8202                 *count = 0;
8203                 return result;
8204         }
8205
8206         *info_p = info;
8207
8208         return WERR_OK;
8209 }
8210
8211 /****************************************************************
8212  _spoolss_EnumPrintProcessors
8213 ****************************************************************/
8214
8215 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8216                                     struct spoolss_EnumPrintProcessors *r)
8217 {
8218         WERROR result;
8219
8220         /* that's an [in out] buffer */
8221
8222         if (!r->in.buffer && (r->in.offered != 0)) {
8223                 return WERR_INVALID_PARAM;
8224         }
8225
8226         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8227
8228         /*
8229          * Enumerate the print processors ...
8230          *
8231          * Just reply with "winprint", to keep NT happy
8232          * and I can use my nice printer checker.
8233          */
8234
8235         *r->out.count = 0;
8236         *r->out.needed = 0;
8237         *r->out.info = NULL;
8238
8239         switch (r->in.level) {
8240         case 1:
8241                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8242                                                      r->out.count);
8243                 break;
8244         default:
8245                 return WERR_UNKNOWN_LEVEL;
8246         }
8247
8248         if (!W_ERROR_IS_OK(result)) {
8249                 return result;
8250         }
8251
8252         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8253                                                      spoolss_EnumPrintProcessors, NULL,
8254                                                      *r->out.info, r->in.level,
8255                                                      *r->out.count);
8256         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8257         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8258
8259         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8260 }
8261
8262 /****************************************************************************
8263  fill_printprocdatatype1
8264 ****************************************************************************/
8265
8266 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8267                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8268                                       const char *name_array)
8269 {
8270         r->name_array = talloc_strdup(mem_ctx, name_array);
8271         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8272
8273         return WERR_OK;
8274 }
8275
8276 /****************************************************************************
8277  enumprintprocdatatypes level 1.
8278 ****************************************************************************/
8279
8280 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8281                                              union spoolss_PrintProcDataTypesInfo **info_p,
8282                                              uint32_t *count)
8283 {
8284         WERROR result;
8285         union spoolss_PrintProcDataTypesInfo *info;
8286
8287         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8288         W_ERROR_HAVE_NO_MEMORY(info);
8289
8290         *count = 1;
8291
8292         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8293         if (!W_ERROR_IS_OK(result)) {
8294                 goto out;
8295         }
8296
8297  out:
8298         if (!W_ERROR_IS_OK(result)) {
8299                 TALLOC_FREE(info);
8300                 *count = 0;
8301                 return result;
8302         }
8303
8304         *info_p = info;
8305
8306         return WERR_OK;
8307 }
8308
8309 /****************************************************************
8310  _spoolss_EnumPrintProcDataTypes
8311 ****************************************************************/
8312
8313 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8314                                        struct spoolss_EnumPrintProcDataTypes *r)
8315 {
8316         WERROR result;
8317
8318         /* that's an [in out] buffer */
8319
8320         if (!r->in.buffer && (r->in.offered != 0)) {
8321                 return WERR_INVALID_PARAM;
8322         }
8323
8324         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8325
8326         *r->out.count = 0;
8327         *r->out.needed = 0;
8328         *r->out.info = NULL;
8329
8330         switch (r->in.level) {
8331         case 1:
8332                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8333                                                         r->out.count);
8334                 break;
8335         default:
8336                 return WERR_UNKNOWN_LEVEL;
8337         }
8338
8339         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8340                                                      spoolss_EnumPrintProcDataTypes, NULL,
8341                                                      *r->out.info, r->in.level,
8342                                                      *r->out.count);
8343         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8344         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8345
8346         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8347 }
8348
8349 /****************************************************************************
8350  fill_monitor_1
8351 ****************************************************************************/
8352
8353 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8354                              struct spoolss_MonitorInfo1 *r,
8355                              const char *monitor_name)
8356 {
8357         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8358         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8359
8360         return WERR_OK;
8361 }
8362
8363 /****************************************************************************
8364  fill_monitor_2
8365 ****************************************************************************/
8366
8367 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8368                              struct spoolss_MonitorInfo2 *r,
8369                              const char *monitor_name,
8370                              const char *environment,
8371                              const char *dll_name)
8372 {
8373         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8374         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8375         r->environment                  = talloc_strdup(mem_ctx, environment);
8376         W_ERROR_HAVE_NO_MEMORY(r->environment);
8377         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8378         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8379
8380         return WERR_OK;
8381 }
8382
8383 /****************************************************************************
8384  enumprintmonitors level 1.
8385 ****************************************************************************/
8386
8387 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8388                                         union spoolss_MonitorInfo **info_p,
8389                                         uint32_t *count)
8390 {
8391         union spoolss_MonitorInfo *info;
8392         WERROR result = WERR_OK;
8393
8394         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8395         W_ERROR_HAVE_NO_MEMORY(info);
8396
8397         *count = 2;
8398
8399         result = fill_monitor_1(info, &info[0].info1,
8400                                 SPL_LOCAL_PORT /* FIXME */);
8401         if (!W_ERROR_IS_OK(result)) {
8402                 goto out;
8403         }
8404
8405         result = fill_monitor_1(info, &info[1].info1,
8406                                 SPL_TCPIP_PORT /* FIXME */);
8407         if (!W_ERROR_IS_OK(result)) {
8408                 goto out;
8409         }
8410
8411 out:
8412         if (!W_ERROR_IS_OK(result)) {
8413                 TALLOC_FREE(info);
8414                 *count = 0;
8415                 return result;
8416         }
8417
8418         *info_p = info;
8419
8420         return WERR_OK;
8421 }
8422
8423 /****************************************************************************
8424  enumprintmonitors level 2.
8425 ****************************************************************************/
8426
8427 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8428                                         union spoolss_MonitorInfo **info_p,
8429                                         uint32_t *count)
8430 {
8431         union spoolss_MonitorInfo *info;
8432         WERROR result = WERR_OK;
8433
8434         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8435         W_ERROR_HAVE_NO_MEMORY(info);
8436
8437         *count = 2;
8438
8439         result = fill_monitor_2(info, &info[0].info2,
8440                                 SPL_LOCAL_PORT, /* FIXME */
8441                                 "Windows NT X86", /* FIXME */
8442                                 "localmon.dll");
8443         if (!W_ERROR_IS_OK(result)) {
8444                 goto out;
8445         }
8446
8447         result = fill_monitor_2(info, &info[1].info2,
8448                                 SPL_TCPIP_PORT, /* FIXME */
8449                                 "Windows NT X86", /* FIXME */
8450                                 "tcpmon.dll");
8451         if (!W_ERROR_IS_OK(result)) {
8452                 goto out;
8453         }
8454
8455 out:
8456         if (!W_ERROR_IS_OK(result)) {
8457                 TALLOC_FREE(info);
8458                 *count = 0;
8459                 return result;
8460         }
8461
8462         *info_p = info;
8463
8464         return WERR_OK;
8465 }
8466
8467 /****************************************************************
8468  _spoolss_EnumMonitors
8469 ****************************************************************/
8470
8471 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8472                              struct spoolss_EnumMonitors *r)
8473 {
8474         WERROR result;
8475
8476         /* that's an [in out] buffer */
8477
8478         if (!r->in.buffer && (r->in.offered != 0)) {
8479                 return WERR_INVALID_PARAM;
8480         }
8481
8482         DEBUG(5,("_spoolss_EnumMonitors\n"));
8483
8484         /*
8485          * Enumerate the print monitors ...
8486          *
8487          * Just reply with "Local Port", to keep NT happy
8488          * and I can use my nice printer checker.
8489          */
8490
8491         *r->out.count = 0;
8492         *r->out.needed = 0;
8493         *r->out.info = NULL;
8494
8495         switch (r->in.level) {
8496         case 1:
8497                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8498                                                    r->out.count);
8499                 break;
8500         case 2:
8501                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8502                                                    r->out.count);
8503                 break;
8504         default:
8505                 return WERR_UNKNOWN_LEVEL;
8506         }
8507
8508         if (!W_ERROR_IS_OK(result)) {
8509                 return result;
8510         }
8511
8512         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8513                                                      spoolss_EnumMonitors, NULL,
8514                                                      *r->out.info, r->in.level,
8515                                                      *r->out.count);
8516         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8517         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8518
8519         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8520 }
8521
8522 /****************************************************************************
8523 ****************************************************************************/
8524
8525 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8526                              const print_queue_struct *queue,
8527                              int count, int snum,
8528                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8529                              uint32_t jobid,
8530                              struct spoolss_JobInfo1 *r)
8531 {
8532         int i = 0;
8533         bool found = false;
8534
8535         for (i=0; i<count && found == false; i++) {
8536                 if (queue[i].job == (int)jobid) {
8537                         found = true;
8538                 }
8539         }
8540
8541         if (found == false) {
8542                 /* NT treats not found as bad param... yet another bad choice */
8543                 return WERR_INVALID_PARAM;
8544         }
8545
8546         return fill_job_info1(mem_ctx,
8547                               r,
8548                               &queue[i-1],
8549                               i,
8550                               snum,
8551                               ntprinter);
8552 }
8553
8554 /****************************************************************************
8555 ****************************************************************************/
8556
8557 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8558                              const print_queue_struct *queue,
8559                              int count, int snum,
8560                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8561                              uint32_t jobid,
8562                              struct spoolss_JobInfo2 *r)
8563 {
8564         int i = 0;
8565         bool found = false;
8566         struct spoolss_DeviceMode *devmode;
8567         NT_DEVICEMODE *nt_devmode;
8568         WERROR result;
8569
8570         for (i=0; i<count && found == false; i++) {
8571                 if (queue[i].job == (int)jobid) {
8572                         found = true;
8573                 }
8574         }
8575
8576         if (found == false) {
8577                 /* NT treats not found as bad param... yet another bad
8578                    choice */
8579                 return WERR_INVALID_PARAM;
8580         }
8581
8582         /*
8583          * if the print job does not have a DEVMODE associated with it,
8584          * just use the one for the printer. A NULL devicemode is not
8585          *  a failure condition
8586          */
8587
8588         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8589         if (nt_devmode) {
8590                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8591                 W_ERROR_HAVE_NO_MEMORY(devmode);
8592                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8593                 if (!W_ERROR_IS_OK(result)) {
8594                         return result;
8595                 }
8596         } else {
8597                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8598                 W_ERROR_HAVE_NO_MEMORY(devmode);
8599         }
8600
8601         return fill_job_info2(mem_ctx,
8602                               r,
8603                               &queue[i-1],
8604                               i,
8605                               snum,
8606                               ntprinter,
8607                               devmode);
8608 }
8609
8610 /****************************************************************
8611  _spoolss_GetJob
8612 ****************************************************************/
8613
8614 WERROR _spoolss_GetJob(pipes_struct *p,
8615                        struct spoolss_GetJob *r)
8616 {
8617         WERROR result = WERR_OK;
8618         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8619         int snum;
8620         int count;
8621         print_queue_struct      *queue = NULL;
8622         print_status_struct prt_status;
8623
8624         /* that's an [in out] buffer */
8625
8626         if (!r->in.buffer && (r->in.offered != 0)) {
8627                 return WERR_INVALID_PARAM;
8628         }
8629
8630         DEBUG(5,("_spoolss_GetJob\n"));
8631
8632         *r->out.needed = 0;
8633
8634         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8635                 return WERR_BADFID;
8636         }
8637
8638         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8639         if (!W_ERROR_IS_OK(result)) {
8640                 return result;
8641         }
8642
8643         count = print_queue_status(snum, &queue, &prt_status);
8644
8645         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8646                      count, prt_status.status, prt_status.message));
8647
8648         switch (r->in.level) {
8649         case 1:
8650                 result = getjob_level_1(p->mem_ctx,
8651                                         queue, count, snum, ntprinter,
8652                                         r->in.job_id, &r->out.info->info1);
8653                 break;
8654         case 2:
8655                 result = getjob_level_2(p->mem_ctx,
8656                                         queue, count, snum, ntprinter,
8657                                         r->in.job_id, &r->out.info->info2);
8658                 break;
8659         default:
8660                 result = WERR_UNKNOWN_LEVEL;
8661                 break;
8662         }
8663
8664         SAFE_FREE(queue);
8665         free_a_printer(&ntprinter, 2);
8666
8667         if (!W_ERROR_IS_OK(result)) {
8668                 TALLOC_FREE(r->out.info);
8669                 return result;
8670         }
8671
8672         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8673                                                r->out.info, r->in.level);
8674         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8675
8676         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8677 }
8678
8679 /****************************************************************
8680  _spoolss_GetPrinterDataEx
8681
8682  From MSDN documentation of GetPrinterDataEx: pass request
8683  to GetPrinterData if key is "PrinterDriverData".
8684 ****************************************************************/
8685
8686 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8687                                  struct spoolss_GetPrinterDataEx *r)
8688 {
8689
8690         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8691         REGISTRY_VALUE          *val = NULL;
8692         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8693         int                     snum = 0;
8694         WERROR result = WERR_OK;
8695
8696         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8697
8698         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8699                 r->in.key_name, r->in.value_name));
8700
8701         /* in case of problem, return some default values */
8702
8703         *r->out.needed  = 0;
8704         *r->out.type    = REG_NONE;
8705
8706         if (!Printer) {
8707                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8708                         OUR_HANDLE(r->in.handle)));
8709                 result = WERR_BADFID;
8710                 goto done;
8711         }
8712
8713         /* Is the handle to a printer or to the server? */
8714
8715         if (Printer->printer_type == SPLHND_SERVER) {
8716                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8717                         "Not implemented for server handles yet\n"));
8718                 result = WERR_INVALID_PARAM;
8719                 goto done;
8720         }
8721
8722         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8723                 return WERR_BADFID;
8724         }
8725
8726         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8727         if (!W_ERROR_IS_OK(result)) {
8728                 goto done;
8729         }
8730
8731         /* check to see if the keyname is valid */
8732         if (!strlen(r->in.key_name)) {
8733                 result = WERR_INVALID_PARAM;
8734                 goto done;
8735         }
8736
8737         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8738                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8739                         "Invalid keyname [%s]\n", r->in.key_name ));
8740                 result = WERR_BADFILE;
8741                 goto done;
8742         }
8743
8744         /* When given a new keyname, we should just create it */
8745
8746         val = get_printer_data(printer->info_2,
8747                                r->in.key_name, r->in.value_name);
8748         if (!val) {
8749                 result = WERR_BADFILE;
8750                 goto done;
8751         }
8752
8753         *r->out.needed = regval_size(val);
8754
8755         if (*r->out.needed > r->in.offered) {
8756                 result = WERR_MORE_DATA;
8757                 goto done;
8758         }
8759
8760         *r->out.type = regval_type(val);
8761
8762         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
8763
8764  done:
8765         if (printer) {
8766                 free_a_printer(&printer, 2);
8767         }
8768
8769         return result;
8770 }
8771
8772 /****************************************************************
8773  _spoolss_SetPrinterDataEx
8774 ****************************************************************/
8775
8776 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8777                                  struct spoolss_SetPrinterDataEx *r)
8778 {
8779         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8780         int                     snum = 0;
8781         WERROR                  result = WERR_OK;
8782         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8783         char                    *oid_string;
8784
8785         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8786
8787         /* From MSDN documentation of SetPrinterDataEx: pass request to
8788            SetPrinterData if key is "PrinterDriverData" */
8789
8790         if (!Printer) {
8791                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8792                         OUR_HANDLE(r->in.handle)));
8793                 return WERR_BADFID;
8794         }
8795
8796         if (Printer->printer_type == SPLHND_SERVER) {
8797                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8798                         "Not implemented for server handles yet\n"));
8799                 return WERR_INVALID_PARAM;
8800         }
8801
8802         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8803                 return WERR_BADFID;
8804         }
8805
8806         /*
8807          * Access check : NT returns "access denied" if you make a
8808          * SetPrinterData call without the necessary privildge.
8809          * we were originally returning OK if nothing changed
8810          * which made Win2k issue **a lot** of SetPrinterData
8811          * when connecting to a printer  --jerry
8812          */
8813
8814         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8815                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8816                         "change denied by handle access permissions\n"));
8817                 return WERR_ACCESS_DENIED;
8818         }
8819
8820         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8821         if (!W_ERROR_IS_OK(result)) {
8822                 return result;
8823         }
8824
8825         /* check for OID in valuename */
8826
8827         oid_string = strchr(r->in.value_name, ',');
8828         if (oid_string) {
8829                 *oid_string = '\0';
8830                 oid_string++;
8831         }
8832
8833         /* save the registry data */
8834
8835         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8836                                     r->in.type, r->in.buffer, r->in.offered);
8837
8838         if (W_ERROR_IS_OK(result)) {
8839                 /* save the OID if one was specified */
8840                 if (oid_string) {
8841                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8842                                 r->in.key_name, SPOOL_OID_KEY);
8843                         if (!str) {
8844                                 result = WERR_NOMEM;
8845                                 goto done;
8846                         }
8847
8848                         /*
8849                          * I'm not checking the status here on purpose.  Don't know
8850                          * if this is right, but I'm returning the status from the
8851                          * previous set_printer_dataex() call.  I have no idea if
8852                          * this is right.    --jerry
8853                          */
8854
8855                         set_printer_dataex(printer, str, r->in.value_name,
8856                                            REG_SZ, (uint8_t *)oid_string,
8857                                            strlen(oid_string)+1);
8858                 }
8859
8860                 result = mod_a_printer(printer, 2);
8861         }
8862
8863  done:
8864         free_a_printer(&printer, 2);
8865
8866         return result;
8867 }
8868
8869 /****************************************************************
8870  _spoolss_DeletePrinterDataEx
8871 ****************************************************************/
8872
8873 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8874                                     struct spoolss_DeletePrinterDataEx *r)
8875 {
8876         POLICY_HND      *handle = r->in.handle;
8877         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8878         int             snum=0;
8879         WERROR          status = WERR_OK;
8880         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8881
8882         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8883
8884         if (!Printer) {
8885                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8886                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8887                 return WERR_BADFID;
8888         }
8889
8890         if (!get_printer_snum(p, handle, &snum, NULL))
8891                 return WERR_BADFID;
8892
8893         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8894                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8895                         "printer properties change denied by handle\n"));
8896                 return WERR_ACCESS_DENIED;
8897         }
8898
8899         if (!r->in.value_name || !r->in.key_name) {
8900                 return WERR_NOMEM;
8901         }
8902
8903         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8904         if (!W_ERROR_IS_OK(status))
8905                 return status;
8906
8907         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8908
8909         if ( W_ERROR_IS_OK(status) )
8910                 mod_a_printer( printer, 2 );
8911
8912         free_a_printer(&printer, 2);
8913
8914         return status;
8915 }
8916
8917 /****************************************************************
8918  _spoolss_EnumPrinterKey
8919 ****************************************************************/
8920
8921 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8922                                struct spoolss_EnumPrinterKey *r)
8923 {
8924         fstring         *keynames = NULL;
8925         int             num_keys;
8926         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8927         NT_PRINTER_DATA *data;
8928         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8929         int             snum = 0;
8930         WERROR          result = WERR_BADFILE;
8931         int i;
8932         const char **array = NULL;
8933
8934
8935         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8936
8937         if (!Printer) {
8938                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8939                         OUR_HANDLE(r->in.handle)));
8940                 return WERR_BADFID;
8941         }
8942
8943         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8944                 return WERR_BADFID;
8945         }
8946
8947         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8948         if (!W_ERROR_IS_OK(result)) {
8949                 return result;
8950         }
8951
8952         /* get the list of subkey names */
8953
8954         data = printer->info_2->data;
8955
8956         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8957         if (num_keys == -1) {
8958                 result = WERR_BADFILE;
8959                 goto done;
8960         }
8961
8962         *r->out.needed = 4;
8963
8964         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
8965         if (!array) {
8966                 result = WERR_NOMEM;
8967                 goto done;
8968         }
8969
8970         for (i=0; i < num_keys; i++) {
8971                 array[i] = talloc_strdup(array, keynames[i]);
8972                 if (!array[i]) {
8973                         result = WERR_NOMEM;
8974                         goto done;
8975                 }
8976
8977                 *r->out.needed += strlen_m_term(keynames[i]) * 2;
8978         }
8979
8980         if (r->in.offered < *r->out.needed) {
8981                 result = WERR_MORE_DATA;
8982                 goto done;
8983         }
8984
8985         result = WERR_OK;
8986
8987         *r->out.key_buffer = array;
8988
8989  done:
8990         if (!W_ERROR_IS_OK(result)) {
8991                 TALLOC_FREE(array);
8992                 ZERO_STRUCTP(r->out.key_buffer);
8993         }
8994
8995         free_a_printer(&printer, 2);
8996         SAFE_FREE(keynames);
8997
8998         return result;
8999 }
9000
9001 /****************************************************************
9002  _spoolss_DeletePrinterKey
9003 ****************************************************************/
9004
9005 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9006                                  struct spoolss_DeletePrinterKey *r)
9007 {
9008         POLICY_HND              *handle = r->in.handle;
9009         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9010         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9011         int                     snum=0;
9012         WERROR                  status;
9013
9014         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9015
9016         if (!Printer) {
9017                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9018                         OUR_HANDLE(handle)));
9019                 return WERR_BADFID;
9020         }
9021
9022         /* if keyname == NULL, return error */
9023
9024         if ( !r->in.key_name )
9025                 return WERR_INVALID_PARAM;
9026
9027         if (!get_printer_snum(p, handle, &snum, NULL))
9028                 return WERR_BADFID;
9029
9030         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9031                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9032                         "printer properties change denied by handle\n"));
9033                 return WERR_ACCESS_DENIED;
9034         }
9035
9036         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9037         if (!W_ERROR_IS_OK(status))
9038                 return status;
9039
9040         /* delete the key and all subneys */
9041
9042         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9043
9044         if ( W_ERROR_IS_OK(status) )
9045                 status = mod_a_printer(printer, 2);
9046
9047         free_a_printer( &printer, 2 );
9048
9049         return status;
9050 }
9051
9052
9053 /********************************************************************
9054  * spoolss_enumprinterdataex
9055  ********************************************************************/
9056
9057 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9058 {
9059         POLICY_HND      *handle = &q_u->handle;
9060         uint32          in_size = q_u->size;
9061         uint32          num_entries,
9062                         needed;
9063         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9064         PRINTER_ENUM_VALUES     *enum_values = NULL;
9065         NT_PRINTER_DATA         *p_data;
9066         fstring         key;
9067         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9068         int             snum;
9069         WERROR          result;
9070         int             key_index;
9071         int             i;
9072         REGISTRY_VALUE  *val;
9073         char            *value_name;
9074         uint32          data_len;
9075
9076
9077         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9078
9079         if (!Printer) {
9080                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9081                 return WERR_BADFID;
9082         }
9083
9084         /*
9085          * first check for a keyname of NULL or "".  Win2k seems to send
9086          * this a lot and we should send back WERR_INVALID_PARAM
9087          * no need to spend time looking up the printer in this case.
9088          * --jerry
9089          */
9090
9091         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9092         if ( !strlen(key) ) {
9093                 result = WERR_INVALID_PARAM;
9094                 goto done;
9095         }
9096
9097         /* get the printer off of disk */
9098
9099         if (!get_printer_snum(p,handle, &snum, NULL))
9100                 return WERR_BADFID;
9101
9102         ZERO_STRUCT(printer);
9103         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9104         if (!W_ERROR_IS_OK(result))
9105                 return result;
9106
9107         /* now look for a match on the key name */
9108
9109         p_data = printer->info_2->data;
9110
9111         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9112         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9113         {
9114                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9115                 result = WERR_INVALID_PARAM;
9116                 goto done;
9117         }
9118
9119         result = WERR_OK;
9120         needed = 0;
9121
9122         /* allocate the memory for the array of pointers -- if necessary */
9123
9124         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9125         if ( num_entries )
9126         {
9127                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9128                 {
9129                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9130                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9131                         result = WERR_NOMEM;
9132                         goto done;
9133                 }
9134
9135                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9136         }
9137
9138         /*
9139          * loop through all params and build the array to pass
9140          * back to the  client
9141          */
9142
9143         for ( i=0; i<num_entries; i++ )
9144         {
9145                 /* lookup the registry value */
9146
9147                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9148                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9149
9150                 /* copy the data */
9151
9152                 value_name = regval_name( val );
9153                 init_unistr( &enum_values[i].valuename, value_name );
9154                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9155                 enum_values[i].type      = regval_type( val );
9156
9157                 data_len = regval_size( val );
9158                 if ( data_len ) {
9159                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9160                         {
9161                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9162                                         data_len ));
9163                                 result = WERR_NOMEM;
9164                                 goto done;
9165                         }
9166                 }
9167                 enum_values[i].data_len = data_len;
9168
9169                 /* keep track of the size of the array in bytes */
9170
9171                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9172         }
9173
9174         /* housekeeping information in the reply */
9175
9176         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9177          * the hand marshalled container size is a multiple
9178          * of 4 bytes for RPC alignment.
9179          */
9180
9181         if (needed % 4) {
9182                 needed += 4-(needed % 4);
9183         }
9184
9185         r_u->needed     = needed;
9186         r_u->returned   = num_entries;
9187
9188         if (needed > in_size) {
9189                 result = WERR_MORE_DATA;
9190                 goto done;
9191         }
9192
9193         /* copy data into the reply */
9194
9195         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9196            response buffer size is != the offered buffer size
9197
9198                 r_u->ctr.size           = r_u->needed;
9199         */
9200         r_u->ctr.size           = in_size;
9201
9202         r_u->ctr.size_of_array  = r_u->returned;
9203         r_u->ctr.values         = enum_values;
9204
9205 done:
9206         if ( printer )
9207         free_a_printer(&printer, 2);
9208
9209         return result;
9210 }
9211
9212 /****************************************************************************
9213 ****************************************************************************/
9214
9215 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9216                                                  const char *servername,
9217                                                  const char *environment,
9218                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9219 {
9220         WERROR werr;
9221         char *path = NULL;
9222
9223         werr = compose_spoolss_server_path(mem_ctx,
9224                                            servername,
9225                                            environment,
9226                                            SPOOLSS_PRTPROCS_PATH,
9227                                            &path);
9228         if (!W_ERROR_IS_OK(werr)) {
9229                 return werr;
9230         }
9231
9232         DEBUG(4,("print processor directory: [%s]\n", path));
9233
9234         r->directory_name = path;
9235
9236         return WERR_OK;
9237 }
9238
9239 /****************************************************************
9240  _spoolss_GetPrintProcessorDirectory
9241 ****************************************************************/
9242
9243 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9244                                            struct spoolss_GetPrintProcessorDirectory *r)
9245 {
9246         WERROR result;
9247
9248         /* that's an [in out] buffer */
9249
9250         if (!r->in.buffer && (r->in.offered != 0)) {
9251                 return WERR_INVALID_PARAM;
9252         }
9253
9254         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9255                 r->in.level));
9256
9257         *r->out.needed = 0;
9258
9259         /* r->in.level is ignored */
9260
9261         result = getprintprocessordirectory_level_1(p->mem_ctx,
9262                                                     r->in.server,
9263                                                     r->in.environment,
9264                                                     &r->out.info->info1);
9265         if (!W_ERROR_IS_OK(result)) {
9266                 TALLOC_FREE(r->out.info);
9267                 return result;
9268         }
9269
9270         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9271                                                r->out.info, r->in.level);
9272         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9273
9274         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9275 }
9276
9277 /*******************************************************************
9278  ********************************************************************/
9279
9280 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9281                                const char *dllname)
9282 {
9283         enum ndr_err_code ndr_err;
9284         struct spoolss_MonitorUi ui;
9285
9286         ui.dll_name = dllname;
9287
9288         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9289                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9290         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9291                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9292         }
9293         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9294 }
9295
9296 /*******************************************************************
9297  Streams the monitor UI DLL name in UNICODE
9298 *******************************************************************/
9299
9300 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9301                                NT_USER_TOKEN *token, DATA_BLOB *in,
9302                                DATA_BLOB *out, uint32_t *needed)
9303 {
9304         const char *dllname = "tcpmonui.dll";
9305
9306         *needed = (strlen(dllname)+1) * 2;
9307
9308         if (out->length < *needed) {
9309                 return WERR_INSUFFICIENT_BUFFER;
9310         }
9311
9312         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9313                 return WERR_NOMEM;
9314         }
9315
9316         return WERR_OK;
9317 }
9318
9319 /*******************************************************************
9320  ********************************************************************/
9321
9322 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9323                              struct spoolss_PortData1 *port1,
9324                              const DATA_BLOB *buf)
9325 {
9326         enum ndr_err_code ndr_err;
9327         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9328                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9329         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9330                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9331         }
9332         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9333 }
9334
9335 /*******************************************************************
9336  ********************************************************************/
9337
9338 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9339                              struct spoolss_PortData2 *port2,
9340                              const DATA_BLOB *buf)
9341 {
9342         enum ndr_err_code ndr_err;
9343         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9344                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9345         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9346                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9347         }
9348         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9349 }
9350
9351 /*******************************************************************
9352  Create a new TCP/IP port
9353 *******************************************************************/
9354
9355 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9356                              NT_USER_TOKEN *token, DATA_BLOB *in,
9357                              DATA_BLOB *out, uint32_t *needed)
9358 {
9359         struct spoolss_PortData1 port1;
9360         struct spoolss_PortData2 port2;
9361         char *device_uri = NULL;
9362         uint32_t version;
9363
9364         const char *portname;
9365         const char *hostaddress;
9366         const char *queue;
9367         uint32_t port_number;
9368         uint32_t protocol;
9369
9370         /* peek for spoolss_PortData version */
9371
9372         if (!in || (in->length < (128 + 4))) {
9373                 return WERR_GENERAL_FAILURE;
9374         }
9375
9376         version = IVAL(in->data, 128);
9377
9378         switch (version) {
9379                 case 1:
9380                         ZERO_STRUCT(port1);
9381
9382                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9383                                 return WERR_NOMEM;
9384                         }
9385
9386                         portname        = port1.portname;
9387                         hostaddress     = port1.hostaddress;
9388                         queue           = port1.queue;
9389                         protocol        = port1.protocol;
9390                         port_number     = port1.port_number;
9391
9392                         break;
9393                 case 2:
9394                         ZERO_STRUCT(port2);
9395
9396                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9397                                 return WERR_NOMEM;
9398                         }
9399
9400                         portname        = port2.portname;
9401                         hostaddress     = port2.hostaddress;
9402                         queue           = port2.queue;
9403                         protocol        = port2.protocol;
9404                         port_number     = port2.port_number;
9405
9406                         break;
9407                 default:
9408                         DEBUG(1,("xcvtcp_addport: "
9409                                 "unknown version of port_data: %d\n", version));
9410                         return WERR_UNKNOWN_PORT;
9411         }
9412
9413         /* create the device URI and call the add_port_hook() */
9414
9415         switch (protocol) {
9416         case PROTOCOL_RAWTCP_TYPE:
9417                 device_uri = talloc_asprintf(mem_ctx,
9418                                 "socket://%s:%d/", hostaddress,
9419                                 port_number);
9420                 break;
9421
9422         case PROTOCOL_LPR_TYPE:
9423                 device_uri = talloc_asprintf(mem_ctx,
9424                         "lpr://%s/%s", hostaddress, queue );
9425                 break;
9426
9427         default:
9428                 return WERR_UNKNOWN_PORT;
9429         }
9430
9431         if (!device_uri) {
9432                 return WERR_NOMEM;
9433         }
9434
9435         return add_port_hook(mem_ctx, token, portname, device_uri);
9436 }
9437
9438 /*******************************************************************
9439 *******************************************************************/
9440
9441 struct xcv_api_table xcvtcp_cmds[] = {
9442         { "MonitorUI",  xcvtcp_monitorui },
9443         { "AddPort",    xcvtcp_addport},
9444         { NULL,         NULL }
9445 };
9446
9447 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9448                                      NT_USER_TOKEN *token, const char *command,
9449                                      DATA_BLOB *inbuf,
9450                                      DATA_BLOB *outbuf,
9451                                      uint32_t *needed )
9452 {
9453         int i;
9454
9455         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9456
9457         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9458                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9459                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9460         }
9461
9462         return WERR_BADFUNC;
9463 }
9464
9465 /*******************************************************************
9466 *******************************************************************/
9467 #if 0   /* don't support management using the "Local Port" monitor */
9468
9469 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9470                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9471                                  DATA_BLOB *out, uint32_t *needed)
9472 {
9473         const char *dllname = "localui.dll";
9474
9475         *needed = (strlen(dllname)+1) * 2;
9476
9477         if (out->length < *needed) {
9478                 return WERR_INSUFFICIENT_BUFFER;
9479         }
9480
9481         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9482                 return WERR_NOMEM;
9483         }
9484
9485         return WERR_OK;
9486 }
9487
9488 /*******************************************************************
9489 *******************************************************************/
9490
9491 struct xcv_api_table xcvlocal_cmds[] = {
9492         { "MonitorUI",  xcvlocal_monitorui },
9493         { NULL,         NULL }
9494 };
9495 #else
9496 struct xcv_api_table xcvlocal_cmds[] = {
9497         { NULL,         NULL }
9498 };
9499 #endif
9500
9501
9502
9503 /*******************************************************************
9504 *******************************************************************/
9505
9506 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9507                                        NT_USER_TOKEN *token, const char *command,
9508                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9509                                        uint32_t *needed)
9510 {
9511         int i;
9512
9513         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9514
9515         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9516                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9517                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9518         }
9519         return WERR_BADFUNC;
9520 }
9521
9522 /****************************************************************
9523  _spoolss_XcvData
9524 ****************************************************************/
9525
9526 WERROR _spoolss_XcvData(pipes_struct *p,
9527                         struct spoolss_XcvData *r)
9528 {
9529         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9530         DATA_BLOB out_data = data_blob_null;
9531         WERROR werror;
9532
9533         if (!Printer) {
9534                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9535                         OUR_HANDLE(r->in.handle)));
9536                 return WERR_BADFID;
9537         }
9538
9539         /* Has to be a handle to the TCP/IP port monitor */
9540
9541         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9542                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9543                 return WERR_BADFID;
9544         }
9545
9546         /* requires administrative access to the server */
9547
9548         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9549                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9550                 return WERR_ACCESS_DENIED;
9551         }
9552
9553         /* Allocate the outgoing buffer */
9554
9555         if (r->in.out_data_size) {
9556                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9557                 if (out_data.data == NULL) {
9558                         return WERR_NOMEM;
9559                 }
9560         }
9561
9562         switch ( Printer->printer_type ) {
9563         case SPLHND_PORTMON_TCP:
9564                 werror = process_xcvtcp_command(p->mem_ctx,
9565                                                 p->server_info->ptok,
9566                                                 r->in.function_name,
9567                                                 &r->in.in_data, &out_data,
9568                                                 r->out.needed);
9569                 break;
9570         case SPLHND_PORTMON_LOCAL:
9571                 werror = process_xcvlocal_command(p->mem_ctx,
9572                                                   p->server_info->ptok,
9573                                                   r->in.function_name,
9574                                                   &r->in.in_data, &out_data,
9575                                                   r->out.needed);
9576                 break;
9577         default:
9578                 werror = WERR_INVALID_PRINT_MONITOR;
9579         }
9580
9581         if (!W_ERROR_IS_OK(werror)) {
9582                 return werror;
9583         }
9584
9585         *r->out.status_code = 0;
9586
9587         memcpy(r->out.out_data, out_data.data, out_data.length);
9588
9589         return WERR_OK;
9590 }
9591
9592 /****************************************************************
9593  _spoolss_AddPrintProcessor
9594 ****************************************************************/
9595
9596 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9597                                   struct spoolss_AddPrintProcessor *r)
9598 {
9599         /* for now, just indicate success and ignore the add.  We'll
9600            automatically set the winprint processor for printer
9601            entries later.  Used to debug the LexMark Optra S 1855 PCL
9602            driver --jerry */
9603
9604         return WERR_OK;
9605 }
9606
9607 /****************************************************************
9608  _spoolss_AddPrinter
9609 ****************************************************************/
9610
9611 WERROR _spoolss_AddPrinter(pipes_struct *p,
9612                            struct spoolss_AddPrinter *r)
9613 {
9614         p->rng_fault_state = true;
9615         return WERR_NOT_SUPPORTED;
9616 }
9617
9618 /****************************************************************
9619  _spoolss_GetPrinterDriver
9620 ****************************************************************/
9621
9622 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9623                                  struct spoolss_GetPrinterDriver *r)
9624 {
9625         p->rng_fault_state = true;
9626         return WERR_NOT_SUPPORTED;
9627 }
9628
9629 /****************************************************************
9630  _spoolss_ReadPrinter
9631 ****************************************************************/
9632
9633 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9634                             struct spoolss_ReadPrinter *r)
9635 {
9636         p->rng_fault_state = true;
9637         return WERR_NOT_SUPPORTED;
9638 }
9639
9640 /****************************************************************
9641  _spoolss_WaitForPrinterChange
9642 ****************************************************************/
9643
9644 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9645                                      struct spoolss_WaitForPrinterChange *r)
9646 {
9647         p->rng_fault_state = true;
9648         return WERR_NOT_SUPPORTED;
9649 }
9650
9651 /****************************************************************
9652  _spoolss_AddPort
9653 ****************************************************************/
9654
9655 WERROR _spoolss_AddPort(pipes_struct *p,
9656                         struct spoolss_AddPort *r)
9657 {
9658         p->rng_fault_state = true;
9659         return WERR_NOT_SUPPORTED;
9660 }
9661
9662 /****************************************************************
9663  _spoolss_ConfigurePort
9664 ****************************************************************/
9665
9666 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9667                               struct spoolss_ConfigurePort *r)
9668 {
9669         p->rng_fault_state = true;
9670         return WERR_NOT_SUPPORTED;
9671 }
9672
9673 /****************************************************************
9674  _spoolss_DeletePort
9675 ****************************************************************/
9676
9677 WERROR _spoolss_DeletePort(pipes_struct *p,
9678                            struct spoolss_DeletePort *r)
9679 {
9680         p->rng_fault_state = true;
9681         return WERR_NOT_SUPPORTED;
9682 }
9683
9684 /****************************************************************
9685  _spoolss_CreatePrinterIC
9686 ****************************************************************/
9687
9688 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9689                                 struct spoolss_CreatePrinterIC *r)
9690 {
9691         p->rng_fault_state = true;
9692         return WERR_NOT_SUPPORTED;
9693 }
9694
9695 /****************************************************************
9696  _spoolss_PlayGDIScriptOnPrinterIC
9697 ****************************************************************/
9698
9699 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9700                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9701 {
9702         p->rng_fault_state = true;
9703         return WERR_NOT_SUPPORTED;
9704 }
9705
9706 /****************************************************************
9707  _spoolss_DeletePrinterIC
9708 ****************************************************************/
9709
9710 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9711                                 struct spoolss_DeletePrinterIC *r)
9712 {
9713         p->rng_fault_state = true;
9714         return WERR_NOT_SUPPORTED;
9715 }
9716
9717 /****************************************************************
9718  _spoolss_AddPrinterConnection
9719 ****************************************************************/
9720
9721 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9722                                      struct spoolss_AddPrinterConnection *r)
9723 {
9724         p->rng_fault_state = true;
9725         return WERR_NOT_SUPPORTED;
9726 }
9727
9728 /****************************************************************
9729  _spoolss_DeletePrinterConnection
9730 ****************************************************************/
9731
9732 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9733                                         struct spoolss_DeletePrinterConnection *r)
9734 {
9735         p->rng_fault_state = true;
9736         return WERR_NOT_SUPPORTED;
9737 }
9738
9739 /****************************************************************
9740  _spoolss_PrinterMessageBox
9741 ****************************************************************/
9742
9743 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9744                                   struct spoolss_PrinterMessageBox *r)
9745 {
9746         p->rng_fault_state = true;
9747         return WERR_NOT_SUPPORTED;
9748 }
9749
9750 /****************************************************************
9751  _spoolss_AddMonitor
9752 ****************************************************************/
9753
9754 WERROR _spoolss_AddMonitor(pipes_struct *p,
9755                            struct spoolss_AddMonitor *r)
9756 {
9757         p->rng_fault_state = true;
9758         return WERR_NOT_SUPPORTED;
9759 }
9760
9761 /****************************************************************
9762  _spoolss_DeleteMonitor
9763 ****************************************************************/
9764
9765 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9766                               struct spoolss_DeleteMonitor *r)
9767 {
9768         p->rng_fault_state = true;
9769         return WERR_NOT_SUPPORTED;
9770 }
9771
9772 /****************************************************************
9773  _spoolss_DeletePrintProcessor
9774 ****************************************************************/
9775
9776 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9777                                      struct spoolss_DeletePrintProcessor *r)
9778 {
9779         p->rng_fault_state = true;
9780         return WERR_NOT_SUPPORTED;
9781 }
9782
9783 /****************************************************************
9784  _spoolss_AddPrintProvidor
9785 ****************************************************************/
9786
9787 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9788                                  struct spoolss_AddPrintProvidor *r)
9789 {
9790         p->rng_fault_state = true;
9791         return WERR_NOT_SUPPORTED;
9792 }
9793
9794 /****************************************************************
9795  _spoolss_DeletePrintProvidor
9796 ****************************************************************/
9797
9798 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9799                                     struct spoolss_DeletePrintProvidor *r)
9800 {
9801         p->rng_fault_state = true;
9802         return WERR_NOT_SUPPORTED;
9803 }
9804
9805 /****************************************************************
9806  _spoolss_FindFirstPrinterChangeNotification
9807 ****************************************************************/
9808
9809 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9810                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9811 {
9812         p->rng_fault_state = true;
9813         return WERR_NOT_SUPPORTED;
9814 }
9815
9816 /****************************************************************
9817  _spoolss_FindNextPrinterChangeNotification
9818 ****************************************************************/
9819
9820 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9821                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9822 {
9823         p->rng_fault_state = true;
9824         return WERR_NOT_SUPPORTED;
9825 }
9826
9827 /****************************************************************
9828  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9829 ****************************************************************/
9830
9831 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9832                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9833 {
9834         p->rng_fault_state = true;
9835         return WERR_NOT_SUPPORTED;
9836 }
9837
9838 /****************************************************************
9839  _spoolss_ReplyOpenPrinter
9840 ****************************************************************/
9841
9842 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9843                                  struct spoolss_ReplyOpenPrinter *r)
9844 {
9845         p->rng_fault_state = true;
9846         return WERR_NOT_SUPPORTED;
9847 }
9848
9849 /****************************************************************
9850  _spoolss_RouterReplyPrinter
9851 ****************************************************************/
9852
9853 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9854                                    struct spoolss_RouterReplyPrinter *r)
9855 {
9856         p->rng_fault_state = true;
9857         return WERR_NOT_SUPPORTED;
9858 }
9859
9860 /****************************************************************
9861  _spoolss_ReplyClosePrinter
9862 ****************************************************************/
9863
9864 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9865                                   struct spoolss_ReplyClosePrinter *r)
9866 {
9867         p->rng_fault_state = true;
9868         return WERR_NOT_SUPPORTED;
9869 }
9870
9871 /****************************************************************
9872  _spoolss_AddPortEx
9873 ****************************************************************/
9874
9875 WERROR _spoolss_AddPortEx(pipes_struct *p,
9876                           struct spoolss_AddPortEx *r)
9877 {
9878         p->rng_fault_state = true;
9879         return WERR_NOT_SUPPORTED;
9880 }
9881
9882 /****************************************************************
9883  _spoolss_RouterFindFirstPrinterChangeNotification
9884 ****************************************************************/
9885
9886 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9887                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9888 {
9889         p->rng_fault_state = true;
9890         return WERR_NOT_SUPPORTED;
9891 }
9892
9893 /****************************************************************
9894  _spoolss_SpoolerInit
9895 ****************************************************************/
9896
9897 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9898                             struct spoolss_SpoolerInit *r)
9899 {
9900         p->rng_fault_state = true;
9901         return WERR_NOT_SUPPORTED;
9902 }
9903
9904 /****************************************************************
9905  _spoolss_ResetPrinterEx
9906 ****************************************************************/
9907
9908 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9909                                struct spoolss_ResetPrinterEx *r)
9910 {
9911         p->rng_fault_state = true;
9912         return WERR_NOT_SUPPORTED;
9913 }
9914
9915 /****************************************************************
9916  _spoolss_RouterReplyPrinterEx
9917 ****************************************************************/
9918
9919 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9920                                      struct spoolss_RouterReplyPrinterEx *r)
9921 {
9922         p->rng_fault_state = true;
9923         return WERR_NOT_SUPPORTED;
9924 }
9925
9926 /****************************************************************
9927  _spoolss_44
9928 ****************************************************************/
9929
9930 WERROR _spoolss_44(pipes_struct *p,
9931                    struct spoolss_44 *r)
9932 {
9933         p->rng_fault_state = true;
9934         return WERR_NOT_SUPPORTED;
9935 }
9936
9937 /****************************************************************
9938  _spoolss_47
9939 ****************************************************************/
9940
9941 WERROR _spoolss_47(pipes_struct *p,
9942                    struct spoolss_47 *r)
9943 {
9944         p->rng_fault_state = true;
9945         return WERR_NOT_SUPPORTED;
9946 }
9947
9948 /****************************************************************
9949  _spoolss_4a
9950 ****************************************************************/
9951
9952 WERROR _spoolss_4a(pipes_struct *p,
9953                    struct spoolss_4a *r)
9954 {
9955         p->rng_fault_state = true;
9956         return WERR_NOT_SUPPORTED;
9957 }
9958
9959 /****************************************************************
9960  _spoolss_4b
9961 ****************************************************************/
9962
9963 WERROR _spoolss_4b(pipes_struct *p,
9964                    struct spoolss_4b *r)
9965 {
9966         p->rng_fault_state = true;
9967         return WERR_NOT_SUPPORTED;
9968 }
9969
9970 /****************************************************************
9971  _spoolss_4c
9972 ****************************************************************/
9973
9974 WERROR _spoolss_4c(pipes_struct *p,
9975                    struct spoolss_4c *r)
9976 {
9977         p->rng_fault_state = true;
9978         return WERR_NOT_SUPPORTED;
9979 }
9980
9981 /****************************************************************
9982  _spoolss_EnumPrinterDataEx
9983 ****************************************************************/
9984
9985 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9986                                   struct spoolss_EnumPrinterDataEx *r)
9987 {
9988         p->rng_fault_state = true;
9989         return WERR_NOT_SUPPORTED;
9990 }
9991
9992 /****************************************************************
9993  _spoolss_53
9994 ****************************************************************/
9995
9996 WERROR _spoolss_53(pipes_struct *p,
9997                    struct spoolss_53 *r)
9998 {
9999         p->rng_fault_state = true;
10000         return WERR_NOT_SUPPORTED;
10001 }
10002
10003 /****************************************************************
10004  _spoolss_55
10005 ****************************************************************/
10006
10007 WERROR _spoolss_55(pipes_struct *p,
10008                    struct spoolss_55 *r)
10009 {
10010         p->rng_fault_state = true;
10011         return WERR_NOT_SUPPORTED;
10012 }
10013
10014 /****************************************************************
10015  _spoolss_56
10016 ****************************************************************/
10017
10018 WERROR _spoolss_56(pipes_struct *p,
10019                    struct spoolss_56 *r)
10020 {
10021         p->rng_fault_state = true;
10022         return WERR_NOT_SUPPORTED;
10023 }
10024
10025 /****************************************************************
10026  _spoolss_57
10027 ****************************************************************/
10028
10029 WERROR _spoolss_57(pipes_struct *p,
10030                    struct spoolss_57 *r)
10031 {
10032         p->rng_fault_state = true;
10033         return WERR_NOT_SUPPORTED;
10034 }
10035
10036 /****************************************************************
10037  _spoolss_5a
10038 ****************************************************************/
10039
10040 WERROR _spoolss_5a(pipes_struct *p,
10041                    struct spoolss_5a *r)
10042 {
10043         p->rng_fault_state = true;
10044         return WERR_NOT_SUPPORTED;
10045 }
10046
10047 /****************************************************************
10048  _spoolss_5b
10049 ****************************************************************/
10050
10051 WERROR _spoolss_5b(pipes_struct *p,
10052                    struct spoolss_5b *r)
10053 {
10054         p->rng_fault_state = true;
10055         return WERR_NOT_SUPPORTED;
10056 }
10057
10058 /****************************************************************
10059  _spoolss_5c
10060 ****************************************************************/
10061
10062 WERROR _spoolss_5c(pipes_struct *p,
10063                    struct spoolss_5c *r)
10064 {
10065         p->rng_fault_state = true;
10066         return WERR_NOT_SUPPORTED;
10067 }
10068
10069 /****************************************************************
10070  _spoolss_5d
10071 ****************************************************************/
10072
10073 WERROR _spoolss_5d(pipes_struct *p,
10074                    struct spoolss_5d *r)
10075 {
10076         p->rng_fault_state = true;
10077         return WERR_NOT_SUPPORTED;
10078 }
10079
10080 /****************************************************************
10081  _spoolss_5e
10082 ****************************************************************/
10083
10084 WERROR _spoolss_5e(pipes_struct *p,
10085                    struct spoolss_5e *r)
10086 {
10087         p->rng_fault_state = true;
10088         return WERR_NOT_SUPPORTED;
10089 }
10090
10091 /****************************************************************
10092  _spoolss_5f
10093 ****************************************************************/
10094
10095 WERROR _spoolss_5f(pipes_struct *p,
10096                    struct spoolss_5f *r)
10097 {
10098         p->rng_fault_state = true;
10099         return WERR_NOT_SUPPORTED;
10100 }
10101